模板拷贝构造与赋值的不对称

今天看了More Effective C++附2中关于auto_ptr的实现,试了一下发现了个很有趣的问题,代码如下:
template < class  T >
class  auto_ptr  {
public:
  
explicit auto_ptr(T *= 0): pointee(p) {}

  template
<class U>
  auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) 
{}
  template<
class U>
  auto_ptr<T>& 
operator=(auto_ptr<U>& rhs)
  
{
    
// VS2005编译出错
    
//if (this != &rhs) reset(rhs.release());
   
// 更改如下
    reset(rhs.release());

    
return *this;
  }
  ~auto_ptr() { delete pointee; }
  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 *= 0)
  
{
    
if (pointee != p) {
      delete pointee;
      pointee 
= p;
    }

  }

  
private:
    T 
*pointee;
    
// VS2005编译不过,也没看出什么用处,注掉
    
//template<class U> friend class auto_ptr<U>;
  }
;

带有模板参数的成员拷贝构造函数和赋值操作符(见粗斜体字代码)能够方便兼容类型的赋值和拷贝构造操作,比如我们有两个具有继承关系的类Base和Derived:
class  Base  
{
public:
    
virtual ~Base()   {   cout << "Base::~Base()" << endl;   }
}
;
class  Derived :  public  Base
{
public:
    
~Derived()   {   cout << "Derived::~Derived()" << endl;   }
}
;

如下操作之所以能够进行完全受益于这两个模板成员函数(下面的spd1和spb1、spd2和spb2都称为兼容类型变量):
    auto_ptr < Derived >  spd1( new  Derived);
       //
 兼容类型拷贝构造
    auto_ptr < Base >  spb1(spd1);
  

    auto_ptr < Derived >  spd2( new  Derived);
    auto_ptr
< Base >  spb2;

        //  兼容类型赋值
    spb2 =  spd2;

然而,More Effective C++附2中的auto_ptr并未提供缺省的拷贝构造和赋值操作,这使得相同类型的auto_ptr变量之间的这两个操作发生了不一致的问题,如下所示:
    auto_ptr < Base >  spb1( new  Base);
    
//  同类型拷贝构造(可利用模板拷贝构造函数)
    auto_ptr < Base >  spb2(spb1);   

    auto_ptr
< Base >  spb3;
    
    
//  同类型赋值(不可利用模板赋值成员函数)
    spb3 =  spb2;

如上面代码注释所示,编译器并未匹配成员模板赋值操作成员函数而是调用了编译器给出的默认版本,这导致的问题显而易见的,它破坏了auto_ptr的原有语义,在变量退出作用域后auto_ptr所管理的资源将被释放不止一次。stl中的实现版本为之提供了缺省拷贝构造和赋值实现。

小结
    本文仅借auto_ptr说事儿,关于智能指针的实现有很多参考如:boost的share_ptr,MFC的Comptr,stl的auto_ptr,Loki的SmartPtr,VOCAL里也有个Sptr……里面都涉及什么引用计数、类型检查和转换、线程安全之类的问题,这里没必要重复。
    本文关注的正如题目所示,其实我并没搞明白怎么回事,如果那位仁兄知道高诉下小弟到更好了。但是,记录下这个细节,在以后的类似代码中多加注意,避免出现类似的隐晦错误是必要的。
   
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值