Smart Pointer访谈录

 
Smart Pointer访谈录
虫 虫
您好,感谢您接受我们的采访。能简单地介绍一下您的名字吗?

    我的英文名叫smart pointer,中文名我自己都不清楚,有人叫我“聪明指针”,有人又叫我“灵巧指针”,还有“智能指针”,都不太爽。不过就连smart pointer也不是名副其实,因为我并不是一个指针(pointer)。

您不是一个指针?那您是?

    其实我是某种形式的类(Class),不过我的特长就是模仿C/C++中的指针,当然大家也就稀里糊涂地叫我 pointer了。所以希望大家一定要记住两点:我是一个类而非指针,但我的特长是模仿指针。

那您怎么做到像指针的呢?

    易容术知道吗?C++的模板技术和运算符重载给了我很大的发挥空间。为了装得像,首先我必须是高度类型化的(strongly typed),模板给了我这个功能;其次我需要模仿指针主要的两个运算符->和*,那就需要进行运算符重载。

这样说似乎很抽象,您能详细说明一下吗?

    其实很容易勾画出中国人的基本特点:黄皮肤、黑头发(大部分老人除外)、能吃苦、能存钱、爱打麻将。当然不排除例外,我只是觉得我接触的大部分中国人都这样。同样,对于smart pointer,也可以给出一个大概的轮廓。

template<class T> class SmartPtr {
  public:
    SmartPtr(T* p = 0);
    SmartPtr(const SmartPtr& p);
    ~SmartPtr();
    SmartPtr& operator =(SmartPtr& p);
    T& operator*() const {return *the_p;}
    T* operator->() const {return the_p;}
  private:
    T *the_p;
}

    正如我所说的,这只是一个大概的印象,很多东西是可以更改的。比如可以去掉或加上一些const,这都需要根据具体的应用环境而定。注意重载运算符*和->,正是它们使我看起来跟普通的指针很相像。而由于我是一个类,在构造函数、析构函数中您都可以通过恰当的编程达到一些不错的效果。

那您能给大家举一个例子吗?

    当然可以。比如C++标准库里的std::auto_ptr就是应用很广的一个例子。它的实现在不同版本的STL中虽有不同,但原理都是一样,大概是下面这个样子:

template<class X> class auto_ptr
{
  public:
    typedef X element_type;
    explicit auto_ptr(X* p = 0) throw(): the_p(p) {}
    auto_ptr(auto_ptr<X>& a) throw():
the_p(a.release()){}

    auto_ptr<X>& operator =(auto_ptr<X>& rhs) throw()
    {
         reset(rhs.release());
         return *this;
    }
    ~auto_ptr() throw() {delete the_p;}
    X& operator* () const throw() {return *the_p;}
    X* operator-> () const throw() {return the_p;}
    X* get () const throw() {return the_p;}
    X* release() throw()
   {
       X* tmp = the_p;
       the_p = 0;
       return tmp;
    }
    void reset(X* p = 0) throw()
   {
      if (the_p!=p)
       {
            delete the_p;
            the_p = p;
       }
    }
   private:
       X* the_p;
};

    关于auto_ptr的使用我不想多说,这不是我们今天的主要话题。它的主要优点是不用delete,可以自动回收已经被分配的空间,由此可以避免资源泄露的问题。很多Java的拥护者经常不分黑白的污蔑C++没有垃圾回收机制,其实不过是贻笑大方而已。抛开在网上许许多多的商业化和非商业化的C++垃圾回收库不提,auto_ptr就足以有效地解决这一问题。并且即使在产生异常的情况下,auto_ptr也能正确地回收资源。这对于写出异常安全(exception-safe)的代码具有重要的意义。

那在使用smart pointer的过程中,是否有什么值得注意的问题呢?

    这个问题就太泛泛了,针对不同的smart pointer,有不同的注意事项。比如auto_ptr,您就不能把它用在标准容器里,因为它只在内存中保留一份实例。不过我相信把握我前面说的两个原则:smart pointer是类而不是指针,是模仿指针,那么一切问题都好办。比如,smart pointer作为一个类,那么以下的做法就可能有问题。

SmartPtr<int> p;
if(p==0)
if(!p)
if(p)

    很显然,p不是一个真正的指针,这么做可能出错。而SmartPtr的设计也是很重要的因素。您可以加上一个bool SmartPtr::null() const来进行判断。如果坚持非要用上面的形式,那也未尝不可。

我们就加上operator void* ()试试:

template<class T> class SmartPtr {
  public:
    ...
    operator void*() const {return the_p;}
    ...
  private:
    T* the_p;
};

这招在basic_ios中就使用过了。这里也可以更灵活地处理,比如类本身需要operator void*()这样地操作,那么上面这招就不灵了。那我们还有重载operator !()等等方法。不怕做不到,只怕想不到。

您能总结一下smart pointer的实质吗?

    smart pointer的实质就是一个外壳,一层包装。正是多了这层包装,我们可以做出许多普通指针无法完成的事,比如前面资源自动回收,或者自动进行引用记数,比如ATL中CComPtr和CComQIPtr这两个COM接口指针类。然而事事都是一把双刃剑,正由于多了这些功能,又会使smart pointer丧失一些功能。一定切记,画虎画皮难画骨,smart pointer毕竟和真正的指针是大大不同的。

非常您接受我们的采访。祝您在中国玩得愉快!

谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值