沒有移動語義的獨特所有權(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_ptrstd::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_ptrs 放入容器中是不安全的。