2. C++智能指针简单介绍
  STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr(本文章暂不讨论)。
  模板auto_ptr是C++98提供的解决方案,C+11已将将其摒弃,并提供了另外两种解决方案。然而,虽然auto_ptr被摒弃,但它已使用了好多年:同时,如果您的编译器不支持其他两种解决力案,auto_ptr将是的选择。
  使用注意点
  所有的智能指针类都有一个explicit构造函数,以指针作为参数。比如auto_ptr的类模板原型为:
  templet<class T>
  class auto_ptr {
  explicit auto_ptr(X* p = 0) ;
  ...
  };
  因此不能自动将指针转换为智能指针对象,必须显式调用:
  shared_ptr<double> pd;
  double *p_reg = new double;
  pd = p_reg;                               // not allowed (implicit conversion)
  pd = shared_ptr<double>(p_reg);           // allowed (explicit conversion)
  shared_ptr<double> pshared = p_reg;       // not allowed (implicit conversion)
  shared_ptr<double> pshared(p_reg);        // allowed (explicit conversion)
  对全部三种智能指针都应避免的一点:
  string vacation("I wandered lonely as a cloud.");
  shared_ptr<string> pvac(&vacation);   // No
  pvac过期时,程序将把delete运算符用于非堆内存,这是错误的。
  使用举例
#include <iostream>
#include <string>
#include <memory>
class report
{
private:
std::string str;
public:
report(const std::string s) : str(s) {
std::cout << "Object created. ";
}
~report() {
std::cout << "Object deleted. ";
}
void comment() const {
std::cout << str << " ";
}
};
int main() {
{
std::auto_ptr<report> ps(new report("using auto ptr"));
ps->comment();
}
{
std::shared_ptr<report> ps(new report("using shared ptr"));
ps->comment();
}
{
std::unique_ptr<report> ps(new report("using unique ptr"));
ps->comment();
}
return 0;
}
  3. 为什么摒弃auto_ptr?
  先来看下面的赋值语句:
  auto_ptr< string> ps (new string ("I reigned lonely as a cloud.”);
  auto_ptr<string> vocation;
  vocaticn = ps;
  上述赋值语句将完成什么工作呢?如果ps和vocation是常规指针,则两个指针将指向同一个string对象。这是不能接受的,因为程序将试图删除同一个对象两次——一次是ps过期时,另一次是vocation过期时。要避免这种问题,方法有多种:
  定义?值运算符,使之执行深复制。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本,缺点是浪费空间,所以智能指针都未采用此方案。
  建立所有权(ownership)概念。对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的构造函数会删除该对象。然后让赋值操作转让所有权。这是用于auto_ptr和uniqiie_ptr 的策略,但unique_ptr的策略更严格。
  创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加1,而指针过期时,计数将减1,。当减为0时才调用delete。这是shared_ptr采用的策略。
  当然,同样的策略也适用于复制构造函数。
  每种方法都有其用途,但为何说要摒弃auto_ptr呢?
  下面举个例子来说明。
#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main() {
auto_ptr<string> films[5] =
{
auto_ptr<string> (new string("Fowl Balls")),
auto_ptr<string> (new string("Duck Walks")),
auto_ptr<string> (new string("Chicken Runs")),
auto_ptr<string> (new string("Turkey Errors")),
auto_ptr<string> (new string("Goose Eggs"))
};
auto_ptr<string> pwin;
pwin = films[2]; // films[2] loses ownership. 将所有权从films[2]转让给pwin,此时films[2]不再引用该字符串从而变成空指针
cout << "The nominees for best avian baseballl film are ";
for(int i = 0; i < 5; ++i)
cout << *films[i] << endl;
cout << "The winner is " << *pwin << endl;
cin.get();
return 0;
}
  运行下发现程序崩溃了,原因在上面注释已经说的很清楚,films[2]已经是空指针了,下面输出访问空指针当然会崩溃了。但这里如果把auto_ptr换成shared_ptr或unique_ptr后,程序不会崩溃,原因如下:
  使用shared_ptr时运行正常,因为shared_ptr采用引用计数,pwin和films[2]都指向同一块内存,在释放空间时因为事先要判断引用计数值的大小因此不会出现多次删除一个对象的错误。
  使用unique_ptr时编译出错,与auto_ptr一样,unique_ptr也采用所有权模型,但在使用unique_ptr时,程序不会等到运行阶段崩溃,而在编译器因下述代码行出现错误:
  unique_ptr<string> pwin;
  pwin = films[2]; // films[2] loses ownership.
  指导你发现潜在的内存错误。
  这是为何要摒弃auto_ptr的原因,一句话总结是:避免潜在的内存崩溃问题。