导读
  近在补看《C++ Primer Plus》第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑。C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等……。而且在看开源的C++项目时,也能随处看到智能指针的影子。这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值。
  下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰。
  目录
  智能指针背后的设计思想
  C++智能指针简单介绍
  为什么摒弃auto_ptr?
  unique_ptr为何优于auto_ptr?
  如何选择智能指针?
  正文
  1. 智能指针背后的设计思想
  我们先来看一个简单的例子:
  void remodel(std::string & str)
  {
  std::string * ps = new std::string(str);
  ...
  if (weird_thing())
  throw exception();
  str = *ps;
  delete ps;
  return;
  }
  当出现异常时(weird_thing()返回true),delete将不被执行,因此将导致内存泄露。
  如何避免这种问题?有人会说,这还不简单,直接在throw exception();之前加上delete ps;不行了。是的,你本应如此,问题是很多人都会忘记在适当的地方加上delete语句(连上述代码中后的那句delete语句也会有很多人忘记吧),如果你要对一个庞大的工程进行review,看是否有这种潜在的内存泄露问题,那是一场灾难!
  这时我们会想:当remodel这样的函数终止(不管是正常终止,还是由于出现了异常而终止),本地变量都将自动从栈内存中删除—因此指针ps占据的内存将被释放,如果ps指向的内存也被自动释放,那该有多好啊。
  我们知道析构函数有这个功能。如果ps有一个析构函数,该析构函数将在ps过期时自动释放它指向的内存。但ps的问题在于,它只是一个常规指针,不是有析构凼数的类对象指针。如果它指向的是对象,则可以在对象过期时,让它的析构函数删除指向的内存。
  这正是 auto_ptr、unique_ptr和shared_ptr这几个智能指针背后的设计思想。我简单的总结下是:将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
  因此,要转换remodel()函数,应按下面3个步骤进行:
  包含头义件memory(智能指针所在的头文件);
  将指向string的指针替换为指向string的智能指针对象;
  删除delete语句。
  下面是使用auto_ptr修改该函数的结果:
  # include <memory>
  void remodel (std::string & str)
  {
  std::auto_ptr<std::string> ps (new std::string(str));
  ...
  if (weird_thing ())
  throw exception();
  str = *ps;
  // delete ps; NO LONGER NEEDED
  return;
  }