C++ 没有移动语义的唯一所有权(auto_ptr)
示例
注意:std::auto_ptr已在C++11中弃用,并将在C++17中删除。仅当您被迫使用C++03或更早版本并且愿意小心时,才应使用此功能。建议与一起移动到unique_ptrstd::move以替换std::auto_ptr行为。
在拥有std::unique_ptr语义之前,我们有了std::auto_ptr。std::auto_ptr提供唯一的所有权,但在复制时转让所有权。
与所有智能指针一样,std::auto_ptr自动清除资源(请参阅RAII):
{ std::auto_ptr<int> p(new int(42)); std::cout << *p; } //p在这里删除,没有内存泄漏
但只允许一个所有者:
std::auto_ptr<X> px = ...; std::auto_ptr<X> py = px; //px现在为空
这允许使用std::auto_ptr来使所有权明确且唯一,以防止意外失去所有权:
void f(std::auto_ptr<X> ) { //承担X的所有权 //在范围末尾将其删除 }; std::auto_ptr<X> px = ...; f(px); //f获得基础X的所有权 //px现在为空 px->foo(); //NPE! //px。〜auto_ptr()不会删除
所有权转移发生在“副本”构造函数中。auto_ptr的副本构造函数和副本赋值运算符通过非const引用获取其操作数,以便可以对其进行修改。一个示例实现可能是:
template <typename T> class auto_ptr { T* ptr; public: auto_ptr(auto_ptr& rhs) : ptr(rhs.release()) { } auto_ptr& operator=(auto_ptr& rhs) { reset(rhs.release()); return *this; } T* release() { T* tmp = ptr; ptr = nullptr; return tmp; } void reset(T* tmp = nullptr) { if (ptr != tmp) { delete ptr; ptr = tmp; } } /* other functions ... */ };
这破坏了复制语义,复制语义要求复制对象使您拥有两个等效版本。对于任何可复制的类型,T我应该能够写出:
T a = ...; T b(a); assert(b == a);
但是对于auto_ptr,情况并非如此。结果,将auto_ptrs放入容器中是不安全的。