auto_ptr是一种智能指针,帮助程序员防止”被异常抛出时发生资源泄露“。auto_prt只是针对某个特定问题而设计,对于其他问题无能为力。新的c++里面已经不提倡使用auto_ptr了。
当你在某个局部new出一些对象的时候,还没有正常的delete,中间抛出了异常,导致无法执行delete,从而导致了资源泄露。而auto_prt保证只要自己被销毁,就一定连带释放其所指向的资源。如:
void f()
{
MyClass* ptr = new MyClass;
try
{
...
}
catch (...)
{
throw;
}
delete ptr; // 当抛出异常时,代码根本不会执行到这里。
}
当使用auto_ptr,就不再需要delete了,当auto_ptr超出了作用域,会自动的回收资源。
auto_ptr<MyClass> ptr(new MyClass);
try
{
...
}
catch (...)
{
throw;
}
auto_ptr的接口与一般指针非常相似。*用来获取所指对象,->用来指向对象中的成员。但是它不能做指针算术。
注意:auto_ptr<> 不允许你使用一般指针惯用的赋值初始化方式,你必须使用数值来完成初始化。
auto_ptr<MyClass> ptr(new MyClass); // 正确
auto_ptr<MyClass> ptr2 = new MyClass; // 错误
auto_ptr是明确的所有观念。由于auto_ptr会删除其所指对象,所以这个对象绝对不能同时被其他对象拥有。绝对不应该出现多个auto_ptr同时拥有一个对象。所以auto_ptr的拷贝构造函数和赋值操作将交出对象的拥有权。
auto_ptr<MyClass> ptr1(new MyClass);
auto_ptr<MyClass> ptr2(ptr1);
第一个语句中ptr1拥有对象,第二个语句中ptr1将对象转交给ptr2,ptr1不再拥有。赋值也差不多
auto_ptr<MyClass> ptr1(new MyClass);
auto_ptr<MyClass> ptr2;
ptr2 = ptr1;
如果ptr2在赋值前拥有对象,那么赋值动作发生时会调用delete将对象删除。
拥有权的转移使得auto_ptr产生了一种特殊的用法:某个函数可以利用auto_ptr将拥有权转交给另一个函数。
向某个函数内传递auto_ptr,如果f不再将ptr1传递出去,那么它指向的对象将在f退出时销毁。
auto_ptr<MyClass> ptr1(new MyClass);
f(ptr1);
函数向外返回auto_ptr。这样,f中的auto_ptr指向对象所有权将转移到了g中。
auto_ptr<MyClass> f()
{
auto_ptr<MyClass> ptr(new MyClass);
return ptr;
}
void g()
{
auto_ptr<MyClass> ptr = f();
}
auto_ptr语义本身就包含了拥有权,如果你无意转交了所有权,就不要用着函数的参数列表和函数返回值中。下面的例子中函数只是想打印出auto_ptr指向的值,却得到了对象的所有权。
template<class T>
void bad_print(auto_ptr<T> ptr)
{
if (ptr.get() == NULL)
{
cout<<"NULL"<<endl;
}
else
{
cout<<*ptr<<endl;
}
}
auto_ptr<int> p(new int);
*p = 42;
bad_print(p); // 所有权转移到了bad_print函数中
*p = 18; // 错误,它不再拥有所有权了
我们可以使用const来保留所有权,防止意外的转移:
const auto_ptr<int> p(new int);
*p = 42;
bad_print(p); // 编译不过
*p = 18;
正确的打印:
template<class T>;
void good_print(T value)
{
cout<<value<<endl;
}
const auto_ptr<int> p(new int);
*p = 42;
good_print(*p); // 不再传递指针
*p = 18; // 正确,依然拥有所有权
good_print(*p);
auto_ptr的错误使用:
- auto_ptr 之间不能共享所有权
- 并不存在针对array而设计的auto_ptr,不要使用new[]所生成的数组作为初值。
- auto_ptr不是一个通用的智能型指针
- auto_ptr不满足stl容器对其元素的要求