vector <unique_ptr>使用push_back调整大小 - 它是如何工作的?</unique_ptr>

时间:2013-04-22 06:27:44

标签: c++ memory vector c++11 smart-pointers

据我所知,当把东西推回到向量中时,有时它必须分配一个新的内存块,导致从旧内存块中复制所有元素,调用它们的析构函数。由于unique_ptr析构函数删除了拥有的内存,它们如何使用向量? 在向量中使用unique_ptr是否安全? 它比常规指针慢吗?

3 个答案:

答案 0 :(得分:12)

  

导致从旧内存块中复制所有元素,调用它们的析构函数。由于unique_ptr析构函数删除了拥有的内存,它们如何使用向量?

事实上,它不再严格地复制元素,而是移动。对于没有隐式或显式移动构造函数的类型,它们是相同的。但是对于unique_ptr来说,这意味着,在新分配的内存中构造新的unique_ptr,给出对“旧”unique_ptr的rvalue引用。他们的移动构造函数做了正确的事情,即它将所有权从旧的unique_ptr转移到新的unique_ptr,将旧版本留空,以便在销毁时不会删除任何内容。

  

在向量中使用unique_ptr是否安全?

只要您尊重语言规则和“C ++常识”,就可以节省使用unique_ptr 无处不在的。这意味着,你必须明确做愚蠢的事情来打破unique_ptr<T> ptr1 {new T()}; unique_ptr<T> ptr2 {ptr1.get()}; //two unique_ptr's owning the same object... 的安全行为。其中包括例如假装将拥有的对象的所有权赋予另一个智能指针:

reinterpret_cast

或涉及memcpymemsetunique_ptr或其他不尊重C ++对象生命周期的其他破坏性操作。

  

它比常规指针慢吗?

也许。与复制原始指针相比,移动unique_ptr时显然会涉及一些小的开销,即将原始设置为零。但是,是否可以优化开销取决于您的编译器和优化器。与性能一样,请咨询您的探查器,以评估 是否更慢以及减速是否重要。我打赌它不会,并考虑到智能指针给你的安全性,从不问vector::reserve()的性能。

旁注:如果您事先知道了矢量的大小,请记住使用unique_ptr。它将为您节省unique_ptr的重新分配和移动。如果你只知道你的向量将具有的近似大小,请不要小 - {{1}} s不是很大(通常与原始指针一样大以及删除器,可能会或可能不会被优化掉) ,所以保留几个百分点不会受到伤害,除非你真的有严格的内存限制。

答案 1 :(得分:6)

使用移动语义,可以将unique_ptr从一个位置移动到另一个位置。这样可以避免在std::move从一个内存位置“移动”到另一个内存位置时指针保持的数据被破坏。

有点像向量增长时从旧向量数组到新内存位置执行浅拷贝。

答案 2 :(得分:3)

根据cppreferencestd::unique_ptr的一个用例用于“移动感知容器”,例如std::vector。这意味着std::vector<T>足够聪明,可以检测T何时可移动,std::unique_ptr就是这种情况,并在调整向量大小时使用移动构造函数。