STL

《Effective STL》

3《确保容器中的副本对象高效而正确》

Posted by Liangjf on April 9, 2019

条目三《确保容器中的副本对象高效而正确》

前两天看的《海王》,真的真的非常好看,全程无尿点。

在STL中,底层操作的都是容器存储的对象的副本。也即,对于STL而言,进去和出来都是一个对象副本。而且在STL的所有操作也只是对存储对象的副本的移动,删除等。

有副本的复制行为,证明必定有拷贝构造函数和赋值操作符重载函数的存在。如果我们没有显示的声明定义,编译器会为我们各自默认的拷贝构造函数和赋值操作符重载函数。

注意点1:

但是由于STL的操作只是对副本的操作,因此编译器默认生成的只是浅拷贝和浅赋值(赋值,其实没有所谓的深浅,因为赋值的目的本来就是单纯的复制一份源对象)。

需要特别注意的是拷贝构造函数。对于一个源对象的拷贝可分为浅拷贝深拷贝。浅拷贝单纯拷贝值类型的值,不会对指针指向的内存拷贝。如果需要,我们必须自己实现拷贝构造函数。

好了,在这里,深浅拷贝构造函数不是重点。还是看看如何正确而高效的使用STL的容器操作,毕竟STL的操作都是副本操作。涉及到副本操作,操作不当,就会造成大量的耗时副本复制行为,造成系统效率低下。

注意点2:

< 创建了一个存放基类对象的容器,向其中插入派生类的对象,那么在派生类对象(通过基类的复制构造函数)被复制进容器时,它所特有的部分(即派生类中的信息)将会丢失。

简单来说,向基类容器插入子类对象,子类对象的特有属性会丢失。

为了容器高效,存储的应该是对象的指针而不是对象。毕竟在,在32位架构中,指针固定是4个细节,64位架构也才8个字节。然而,对于对象而言,即使只有最基本的默认构造函数,析构函数,拷贝构造函数等,已经不止8个字节了。

所以为了高效,在使用STL容器时,鼓励是存储指针而不是对象。因为,在存储的对象越来越多时,大量的对象复制行为的耗时是可观的。并且指针没有深浅拷贝的区别,也没有剥离问题发生。

注意点3:

但是,在存储指针的时候,也有烦恼的事情,一个容易想到的问题是,容器存储的指针的管理问题,如果在使用时已释放就会造成coredump。所以一个好的建议是使用智能指针

看起来,STL容器一直在复制和操作副本,相比数组有什么优势?最简单的是自动扩容,当插入数据时内存不够会自动申请新的内存块并做数据搬移工作。达到有多少米吃多少饭的目的,绝不会也不能浪费不必要的内存。这是一大进步啊!