一、auto_ptr设计动机
auto_ptr智能型指针,主要用来处理显示开辟内存(new),而忽略释放内存(delete)或程序抛出异常内存得不到释放的情况。该指针保证在任何情形下,只要自己被摧毁,就一定连带释放其所指资源。
例如,一般new一个对象,我们这么处理:
ClassA *ptr = new ClassA;
后续使用,一定要记得释放delete
delete ptr;
但是如果我们采用auto_ptr,则只需这么处理:
std::auto_ptr<ClassA> ptr(new ClassA);
不再需要delete,遇到异常也不用catch处理。
注意:auto_ptr<>不允许使用一般指针惯用的赋值初始化方式。必须使用数值来完成初始化。
std::auto_ptr<ClassA> ptr1(new ClassA); //OK
std::auto_ptr<ClassA> ptr2 = new ClassA; //ERROR
二、auto_ptr拥有权的转移由于auto_ptr会删除其所指对象,所以这个对象绝对不能被其他对象“拥有”。绝对不应该出现多个auto_ptr同时拥有一个对象的情况。
std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2(ptr1);
拥有权由ptr1转交给ptr2,这样对象只会被delete一次,即在ptr2被销毁的时候。
同理,赋值动作也是如此:
std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2;
ptr2 = ptr1;
注意:只有auto_ptr可以拿来当做另一个auto_ptr的初值,普通指针是不行的。
std::auto_ptr<ClassA> ptr;
ptr = new ClassA; //ERROR
ptr = std::auto_ptr<ClassA> (new ClassA); //OK
三、缺陷
auto_ptr语义本身就包含了拥有权,所以如果你无意转交了你的拥有权,就不要在参数列中使用auto_ptr,也不要以它作为返回值。例如auto_ptr当做参数
template<class T>
void bad_print(std::auto_ptr<T> p)
{
if (p.get() == NULL)
{
std::cout<<"NULL";
}
else
{
std::cout<<*p;
}
}
由于作为参数的auto_ptr会将拥有权转交给参数p,而当函数退出时,会删除p所拥有的对象。这样会导致致命的执行期错误,如下使用:
std::auto_ptr<int> p(new int);
*p = 42;
bad_print(p);
*p = 18;
如果不想发生拥有权的转移,可以将参数声明为const引用
template<class T>
void bad_print(const std::auto_ptr<T>& p)
{
if (p.get() == NULL)
{
std::cout<<"NULL";
}
else
{
std::cout<<*p;
}
}