智能指针是一个好东西:跟内建指针一样使用,但是可以自动释放heap上得资源。
智能指针是一个类类型(通常采用类模板来实现),它乔装成一个指针,但额外提供了内建指针无法提供的能力。通常而言,一个智能指针使用类的构造函数、析构函数和复制操作符所提供的能力。来控制(或跟踪)对它所指向的东西的访问。
所有的智能指针都重载->和*操作符,有的甚至还重载了->*操作符(参见“指向类成员的指针并非指针”)。另外有些智能指针(尤其是STL)还重载了++/—/-/+/+=/-=/[]等。
可以利用模板做一个简单的smart pointer;下面是一个能实现执行一个检查,确保在被使用之前不为空:
template <typename T>
class CheckedPtr{
public:
explicit CheckedPtr( T*p) :p_(p){}
~ CheckedPtr() {delete p_;}
T* operator->() { return get();}
T& operator*() { return *get();}
private:
T* p_;
T* get(){
if(!p_){
throw NullCheckedPointer();
}
return p_;
}
CheckedPtr(const CheckedPtr &);
CheckedPtr & operator=( const CheckedPtr & );
};
在C++中,标准库已经提供了一个资源句柄模板,那就是auto_ptr。
它像所有智能指针一样,有很多好处。
首先,性能非常高。其次,当auto_ptr离开作用域,其析构函数将释放它所指向的任何东西。第三,在类型转换方面,其行为酷似内建指针。
不过他也有特殊之处。
他的复制操作,会影响到参与复制的双方。对auto_ptr而言,复制和初始化并不是真正的复制操作,他们实际上把底层对象的控制权从一个auto_ptr转移到另一个auto_ptr(控制权转移)。所以,在容器中要避免使用它,因为容器一般遵从普通的复制语义而不是转移语义。
vector<auto_ptr<Shape>> shapes; //糟糕的主意
再者,一个auto_ptr应该之争单个元素,而不是一个数组。原因在于,它使用op delete而不是op delete[]来执行删除操作。
auto_ptr<int> ints( new int[32] ); //糟糕的主意
对于指向数组的auto_ptr来说,使用标准库的vector是一个不错的选择。