C++ Exceptional 有关auto_ptr使用需要注意的地方

auto_ptr是C++11之前标准库里带的一个通用的智能指针,但说实话很多人可能并不喜欢用这个东西,因为它有时会带来一些意想不到的bug,而正是auto_ptr的实现方式才导致了这些问题的产生,下面我详细叙述一下这里的前因后果。

首先,作为一个智能指针对象,auto_ptr是没有引用计数的概念的,所以这就导致了一个问题:
当一个auto_ptr由另一个auto_ptr拷贝构造或者赋值的时候,这个时候,对象的所有权应该怎么办呢。首先,因为没有引用计数,所以不能通过加引用计数的方式来进行赋值或者拷贝。但如果不利用引用计数,而直接进行拷贝,那么相当于说两个auto_ptr持有相同的一个内部指针,这样的后果就是导致这个指针会被重复释放,从而引起错误。c++标准库为了避免这种错误,所以在设计auto_ptr时,是用的所有权转移的方式来实现拷贝构造和赋值构造的。这样的话,原生指针在某个时间只可能被一个auto_ptr对象所拥有,从而避免了重复释放的问题。而也正是这种实现方式,才有了下面的几个错误的使用auto_ptr的方式:

  • 不要引用已经转移所有权的auto_ptr
std::auto_ptr a(new T());
std::auto_ptr b = a;
a->func() or *a 等等

这种的错误根源在于把a对对象T的所有权转移给b后,又去使用a对象去访问原生指针,这样肯定是会出错的,因为a对象中的原生指针已经是null了

  • 不要把auto_ptr放入标准容器中
vector<auto_ptr> v;

切记,auto_ptr是不能放置在标准容器里的,这也是由于auto_ptr的特性决定的。因为标准容器里的对象要满足一个要求,那就是对象之间是互等的复制,也就是说,对象复制后这两个对象是完全相等的。而auto_ptr显然不能满足这个要求,因为auto_ptr在复制的过程中伴随着原生指针所有权的转移。

  • auto_ptr作为类的成员变量时,注意类的拷贝构造和赋值构造函数
class C
{
public: /*...*/
protected: /*...*/
private: /*...*/
    auto_ptr pimpl_;
}

如上,当把auto_ptr当作类的成员函数时,这个时候要特别注意类的拷贝构造函数和赋值构造函数,因为两个类之间的赋值或者拷贝,会把其中一个类的auto_ptr置空,这个时候,你要想一下,这是不是你想要的结果。

说了以上这么多,总起来说,auto_ptr存在的问题还是挺多的,这也正是大家不太喜欢用它的原因。当然boost库中或者C++11后,有了更好的替换auto_ptr的智能指针,shared_ptr和unique_ptr,大家在开发过程中可以安全地使用这两种类型的智能指针。

你可能感兴趣的:(C++)