More Effective C++ Item 附2:一个auto_ptr的实现实例

原创 2002年03月31日 15:46:00

More Effective C++的前言、导读和附1(侯捷译),以及 “C++ 中计算物件个数”和“为智能指标实作 operator->*”(陈崴译,原发表于程序员杂志),可在侯捷的站点下载到。

 

一个auto_ptr的实现实例
Items M9、M10、E26、E31和E32证明了auto_ptr模板类的非同寻常的作用。不幸的是,目前很少有编译器地提供了一个“正确”的实现(注1)。Items M9和M28大致描述了你怎么自己实现一个,但从事实际项目时有一个更详尽的版本就太好了。
下面是两个auot_ptr的实现。第一个版本文档化了类的接口并在类的定义体外面实现了所有的成员函数。第二个版本将所有的成员函数都实现在定义体内了。在文体上,第二个实现不如第一个,因为它没有将类的接口从实现中分离出来。但,auto_ptr只是一个简单的类,所以第二个实现比第一个清晰得多。
这是有专门接口申明的auto_ptr模板:
template<class T>
class auto_ptr {
public:
  explicit auto_ptr(T *p = 0);              // Item M5 有“explicitfor”
                                            // 的描述
  template<class U>                         // 拷贝构造函数成员模板
  auto_ptr(auto_ptr<U>& rhs);               //  (见Item M28):
                                            // 用另一个类型兼容的
                                            // auto_ptr对象
                                            // 初始化一个新的auto_ptr对象
  ~auto_ptr();
  template<class U>                         // 赋值操作成员模板
  auto_ptr<T>&                              // (见Item M28):
  operator=(auto_ptr<U>& rhs);              // 用另一个类型兼容的
                                            // auto_ptr对象给它赋值
  T& operator*() const;                     // 见Item M28
  T* operator->() const;                    // 见Item M28
  T* get() const;                           // 返回包容指针的
                                            // 当前值
  T* release();                             // 放弃包容指针的
                                            // 所有权,
                                            // 并返回其当前值
  void reset(T *p = 0);                     // 删除包容指针,
                                            // 获得指针p的所有权
private:
  T *pointee;
template<class U>                           // 让所有的auto_ptr类
friend class auto_ptr<U>;                   // 成为友元
};
template<class T>
inline auto_ptr<T>::auto_ptr(T *p)
: pointee(p)
{}
template<class T>
  inline auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs)
  : pointee(rhs.release())
  {}
template<class T>
inline auto_ptr<T>::~auto_ptr()
{ delete pointee; }
template<class T>
  template<class U>
  inline auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<U>& rhs)
  {
    if (this != &rhs) reset(rhs.release());
    return *this;
  }
template<class T>
inline T& auto_ptr<T>::operator*() const
{ return *pointee; }
template<class T>
inline T* auto_ptr<T>::operator->() const
{ return pointee; }
template<class T>
inline T* auto_ptr<T>::get() const
{ return pointee; }
template<class T>
inline T* auto_ptr<T>::release()
{
  T *oldPointee = pointee;
  pointee = 0;
  return oldPointee;
}
template<class T>
inline void auto_ptr<T>::reset(T *p)
{
  if (pointee != p) {
    delete pointee;
    pointee = p;
  }
}
    这是所有函数定义在类定义体内的auto_ptr模板。如你所见,它不会搞乱大脑:
template<class T>
class auto_ptr {
public:
  explicit auto_ptr(T *p = 0): pointee(p) {}
  template<class U>
  auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {}
  ~auto_ptr() { delete pointee; }
  template<class U>
  auto_ptr<T>& operator=(auto_ptr<U>& rhs)
  {
    if (this != &rhs) reset(rhs.release());
    return *this;
  }
  T& operator*() const { return *pointee; }
  T* operator->() const { return pointee; }
  T* get() const { return pointee; }
  T* release()
  {
    T *oldPointee = pointee;
    pointee = 0;
    return oldPointee;
  }
  void reset(T *p = 0)
  {
    if (pointee != p) {
      delete pointee;
      pointee = p;
    }
  }
  private:
    T *pointee;
  template<class U> friend class auto_ptr<U>;
  };
如果你所用的编译器还不支持“explicit”,可以安全地用#define取消它的存在:
#define explicit
这不会造成auto_ptr的任何功能减弱,但导致轻微的安全性减弱。详见Item M5。
如果你的编译器不支持成员模板,你可以使用非模板的auto_ptr拷贝构造函数和赋值操作(描述在Item M28)。这将造成你的auto_ptr在使用上有些小小的不方便,但没有其它方法能模仿成员模板的行为,唉!如果成员模板(或语言中的其它一些特性)对你非常重要,告诉你的编译器提供商。越多的用户要求新的语言特性,提供商将越快地实现它们。
* 注1:
这主要是因为auto_ptr的标准长年来一直没有确定。其最终描述被采纳于1997年11月。其细节可参考本书的主页。注意,此处的auto_ptr版本在实现上比正式版本在具体细节上有小小的省略:实际上auto_ptr位于名字空间std中(见Item M35)并且其成员函数承诺不抛任何异常。

(大卫的阅读笔记)More Effective C++ Item 附2:一个auto_ptr的实现实例

Davids Note: I am not a good writer, and to write a fully new article is a little hard for me. But w...
  • billdavid
  • billdavid
  • 2004年10月26日 18:26
  • 1940

《More Effective C++》读书笔记-技术

25、将构造函数和非成员函数虚化1、这里所谓的虚拟构造函数,并不是真的指在构造函数前面加上 virtual 修饰符,而是指能够根据传入不同的参数建立不同继承关系类型的对象。class NLCompon...
  • will130
  • will130
  • 2016年05月02日 12:27
  • 2791

《Effective C++》和《More Effective C++》汇总

More Effective C++读书笔记 条款1:指针与引用的区别 二者之间的区别是:在任何情况下都不能用指向空值的引用,而指针则可以;指针可以被重新赋值以指向另一个不同的对象,但...
  • zhu2695
  • zhu2695
  • 2013年06月22日 20:29
  • 2032

Item 31:最小化文件之间的编译依赖 Effective C++笔记

Item 31: Minimize compilation dependencies between files. 曾听老师讲过,每天上班的第一件事就是下载最新代码开始编译,然后可以有半个小...
  • yangjvn
  • yangjvn
  • 2015年09月19日 11:56
  • 860

More Effective C++ 读书摘要(目录索引)

一、基础议题 Item 1. 区分指针和引用Item 2. 优先考虑C++风格的类型转换Item 3. 决不要把多态用于数组Item 4. 避免不必要的默认构造函数二、运算符Item 5. 小心用户自...
  • thy38
  • thy38
  • 2009年04月26日 10:23
  • 1305

[More Effective C++]尽量使用C++风格的类型转换

Item M2:尽量使用C++风格的类型转换 1、C不支持一下转换: 1)把一个指向const 对象的指针(pointer-to-const-object)转换成指向const 对象的指针(poin...
  • AlphaGQ
  • AlphaGQ
  • 2017年04月10日 21:27
  • 281

《Effective C++》:条款46-条款47

条款46需要类型转换时请为模板定义非成员函数 条款47请使用traits class表现类型信息条款...
  • KangRoger
  • KangRoger
  • 2015年03月13日 22:10
  • 1361

More Effective中auto_ptr实现

template class auto_ptr { public : //使用explicit关键字避免隐式转换 explicit auto_ptr(T* p=...
  • DHL1234567
  • DHL1234567
  • 2014年09月03日 22:36
  • 501

《More Effective C++》读书笔记-异常

9、利用destructors 避免泄漏资源使用指针时,如果在delete指针之前产生异常,将会导致不能删除指针,从而产生资源泄漏。解决办法: 1、使用try-catch语句。int *pi = n...
  • will130
  • will130
  • 2016年04月30日 19:24
  • 277

Item 35:考虑虚函数的其他替代设计 Effective C++笔记

Item 35: Consider alternatives to virtual functions. 比如你在开发一个游戏,每个角色都有一个healthValue()方法。很显然你应该把...
  • yangjvn
  • yangjvn
  • 2015年09月25日 11:23
  • 834
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:More Effective C++ Item 附2:一个auto_ptr的实现实例
举报原因:
原因补充:

(最多只允许输入30个字)