11

据我了解,当将东西 push_back 放入向量时,有时它必须分配一个新的内存块,导致将所有元素从旧内存块复制到其中,调用它们的析构函数。由于 unique_ptr 析构函数删除了拥有的内存,它们怎么可能与向量一起使用?在向量中使用 unique_ptr 是否安全?它比普通指针慢吗?

4

3 回答 3

14

导致将所有元素从旧内存块复制到其中,调用它们的析构函数。由于 unique_ptr 析构函数删除了拥有的内存,它们怎么可能与向量一起使用?

事实上,它不再是严格地复制元素,而是在移动。对于没有隐式或显式移动构造函数的类型,也是如此。但是对于unique_ptrs 这意味着,新的 s 是在新分配的内存中构造的,给定对“旧” sunique_ptr的右值引用。unique_ptr他们的移动构造函数做了正确的事情,即它将所有权从旧的转移到新unique_ptr的,让旧的为空,因此当它们被销毁时没有任何内容被删除。

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

只要您尊重语言规则和“C++ 常识”,在任何地方都可以使用unique_ptrs 。这意味着,您将不得不明确地做一些愚蠢的事情来破坏安全行为。其中包括假装将拥有对象的所有权赋予另一个智能指针:unique_ptr

unique_ptr<T> ptr1 {new T()};
unique_ptr<T> ptr2 {ptr1.get()}; //two unique_ptr's owning the same object...

reinterpret_cast或一些涉及,memcpymemset其他不尊重 C++ 对象生命周期的破坏性操作。

它比普通指针慢吗?

也许。与复制原始指针相比,移动 a 显然会涉及一些小的开销unique_ptr,即将原始指针设置为零。但是是否可以优化该开销取决于您的编译器和优化器。与以往一样,请咨询您的分析器以评估它是否较慢以及减速是否重要。我敢打赌它不会,并且考虑到智能指针会给你带来的安全性,只是永远不要询问unique_ptr' 的性能。

旁注:如果您事先知道矢量的大小,请记住使用vector::reserve(). 它将为您节省unique_ptrs 的重新分配和移动。如果你只知道你的向量的大概大小,不要unique_ptr小题大做——s不是很大(通常和原始指针加上删除器一样大,可能会或可能不会被优化掉),所以保留一些除非你真的有严格的内存限制,否则百分之几不会受到伤害。

于 2013-04-22T07:24:56.557 回答
6

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

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

于 2013-04-22T06:32:19.760 回答
4

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

于 2013-04-22T06:31:29.047 回答