据我了解,当东西被pushed_back到向量中时,有时它必须分配一个新的内存块,导致将所有元素从旧内存块复制到其中,调用它们的析构函数。既然unique_ptr析构函数会删除拥有的内存,那么它们怎么可能与 vector 一起使用?在载体中使用unique_ptr安全吗?它比常规指针慢吗?
导致将所有元素从旧内存块复制到其中,调用它们的析构函数。既然unique_ptr析构函数会删除拥有的内存,那么它们怎么可能与 vector 一起使用?
事实上,它不再是严格复制元素,而是在移动。对于没有隐式或显式移动构造函数的类型,这是相同的。但对于unique_ptr
来说,这意味着新的unique_ptr
是在新分配的内存中构造的,给定对"旧"unique_ptr
s的重值引用。他们的移动构造函数做了正确的事情,即它将所有权从旧unique_ptr
转移到新,将旧的留空,因此在它们被销毁时不会删除任何内容。
只要在载体中使用unique_ptr安全吗?
您尊重语言规则和"C++常识",就可以在任何地方使用unique_ptr
。这意味着,您必须明确地做愚蠢的事情来破坏unique_ptr
的安全行为。其中包括例如假装将拥有对象的所有权交给另一个智能指针:
unique_ptr<T> ptr1 {new T()};
unique_ptr<T> ptr2 {ptr1.get()}; //two unique_ptr's owning the same object...
或一些涉及reinterpret_cast
、memcpy
、memset
或其他不尊重对象生存期C++内容的破坏性行为。
它比常规指针慢吗?
或。与复制原始指针(即将原始指针设置为零(相比,移动unique_ptr
显然涉及一些小开销。但是,是否可以优化该开销取决于您的编译器和优化器。与性能一样,请咨询探查器以评估性能是否变慢以及速度减慢是否重要。我敢打赌它不会,考虑到智能指针会给你带来的安全性,永远不要问unique_ptr
的性能。
旁注:如果您事先知道矢量的大小,请记住使用 vector::reserve()
.它将为您节省unique_ptr
的重新分配和移动。如果你只知道你的矢量的近似大小,不要小气 - unique_ptr
不是很大(通常和原始指针加上删除器一样大,可能会也可能不会被优化掉(,所以保留百分之几不会有什么坏处,除非你真的有严格的内存限制。
使用移动语义,可以将unique_ptr从一个位置移动到另一个位置。这将避免指针在从一个内存位置"移动"到另一个内存位置时std::move
存储的数据被破坏。
这有点像随着矢量的增长执行从旧矢量数组到新内存位置的浅拷贝。
根据 cpp首选项,std::unique_ptr
的一个用例是在"移动感知容器"中使用,例如 std::vector
。这意味着std::vector<T>
足够聪明,可以检测T
何时可移动,std::unique_ptr
就是这种情况,并在调整矢量大小时使用移动构造函数。