沒有移動語義的獨特所有權(auto ptr)
Version < C++ 11
注意: std::auto_ptr
已在 C++ 11 中棄用,將在 C++ 17 中刪除。如果你被迫使用 C++ 03 或更早版本並且願意小心,你應該只使用它。建議結合 std::move
移至 unique_ptr 以取代 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 is deleted here, no memory leaked
但只允許一個所有者:
std::auto_ptr<X> px = ...;
std::auto_ptr<X> py = px;
// px is now empty
這允許使用 std::auto_ptr 來保持所有權的顯式和唯一性,以免意外失去所有權:
void f(std::auto_ptr<X> ) {
// assumes ownership of X
// deletes it at end of scope
};
std::auto_ptr<X> px = ...;
f(px); // f acquires ownership of underlying X
// px is now empty
px->foo(); // NPE!
// px.~auto_ptr() does NOT delete
所有權的轉移發生在複製建構函式中。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_ptr
s 放入容器中是不安全的。