c – 对于数据成员,如果包含的对象已经在动态内存中,那么动态分
我首先假设一般来说,在堆栈中分配小对象,在动态内存中分配大对象是个好主意.另一个假设是,在尝试学习内存,STL容器和智能指针时,我可能会感到困惑.
考虑下面的例子,我有一个必须通过智能指针在免费商店中分配的对象,例如,我可以依赖客户从工厂获取所述对象.此对象包含一些使用STL容器专门分配的数据,该容器恰好是std :: vector.在一种情况下,这个数据向量本身是使??用一些智能指针动态分配的,而在另一种情况下我只是不使用智能指针. 设计A和设计B之间是否存在实际差异,如下所述? 情况A: class SomeClass{ public: SomeClass(){ /* initialize some potentially big STL container */ } private: std::vector<double> dataVector_; }; 情况B: class SomeOtherClass{ public: SomeOtherClass() { /* initialize some potentially big STL container,but is it allocated in any different way? */ } private: std::unique_ptr<std::vector<double>> pDataVector_; }; 一些工厂功能. std::unique_ptr<SomeClass> someClassFactory(){ return std::make_unique<SomeClass>(); } std::unique_ptr<SomeOtherClass> someOtherClassFactory(){ return std::make_unique<SomeOtherClass>(); } 使用案例: int main(){ //in my case I can reliably assume that objects themselves //are going to always be allocated in dynamic memory auto pSomeClassObject(someClassFactory()); auto pSomeOtherClassObject(someOtherClassFactory()); return 0; } 我希望两种设计选择都有相同的结果,但它们呢? tl; dr:智能指针指向STL容器是不是错了? 编辑: 解决方法
在这里使用std :: unique_ptr只是浪费,除非你的目标是编译器防火墙(基本上将编译时依赖性隐藏到vector,但是你需要向标准容器转发声明).
你正在添加一个间接,但更重要的是,SomeClass的全部内容在访问内容时变成3个独立的内存块(SomeClass与/包含指向std :: vector的块指向其元素数组的unique_ptr的块).此外,您还需要支付额外多余的堆开销. 现在你可能开始想象一个间接对向量有帮助的场景,比如你可以在两个SomeClass实例之间浅移/交换unique_ptrs.是的,但是矢量已经提供了没有unique_ptr包装器的顶部.它已经有像空的状态,你可以重用一些有效/无效的概念. 请记住,可变大小的容器本身是小对象,而不是大对象,指向潜在的大块.矢量不大,其动态内容可以.为大对象添加间接的想法并不是一个坏的经验法则,但矢量不是一个大的对象.随着移动语义的到位,值得一提的是它更像是一个指向一个可以被浅层复制和廉价交换的大内存块.在移动语义之前,有更多的理由认为像std :: vector这样的东西是一个不可分割的大对象(尽管它的内容总是可以交换),但是现在值得把它想象成一个指向大而动态内容的小手柄. 通过unique_ptr之类的东西引入间接的一些常见原因是: >抽象&躲了起来.如果你试图抽象或隐藏某些类型/子类型Foo的具体定义,那么这就是你需要间接的地方,这样它的句柄就可以被那些不知道的人捕获(或者甚至可能用于抽象)正是Foo是什么. 现在将shared_ptr包装在标准容器之上可能会有更多合法的应用程序,如果您有一个容器实际上可以由多个所有者(合理地)拥有.使用unique_ptr,一次只有一个所有者可以拥有该对象,标准容器已经允许您交换并移动彼此的内部内部(大的动态部分).所以我没有理由用直接用unique_ptr包装一个标准容器,因为它已经有点像一个动态数组的智能指针(但有更多的功能来处理动态数据,包括深层复制它,如果需要) . 如果我们谈论非标准容器,比如说你正在使用提供一些数据结构的第三方库,这些数据结构的内容可能会变得非常大但是它们无法提供那些廉价,无效的移动/交换语义,那么你可能表面上将它包装在unique_ptr周围,交换一些创建/访问/破坏开销,以便将这些廉价的移动/交换语义作为一种解决方法.对于标准容器,不需要这样的解决方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |