没有移动语义的独特所有权(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 放入容器中是不安全的。