被无视的伊谢尔伦

雕栏玉砌应犹在,只是朱颜改

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  9 随笔 :: 0 文章 :: 6 评论 :: 0 Trackbacks

例如有以下class:

class  StringBad
{
    
private :
        
char   *  str;
        
int  len;
         
    
public :
        StringBad(
const   char   *  s);
        StringBad();
        
~ StringBad();
        
}
;

在构造函数和析构函数定义当中有如下定义:

StringBad::StringBad( const   char   *  s)
{
    len 
=  std::strlen(s);
    str 
=   new   char  [len  +   1 ];
    
}
 

StringBad::StringBad()
{
    len 
=   4  ;
    str 
=   new   char [ 4 ];
    
}
 

StringBad::
~ StringBad()
{
    
    delete [] str;
}

那么在程序当中如果有以下代码:

StringBad sports( " Spinach Leaves Bow1 for bollars " );
StringBad sailor 
=  sports;

以上的第二条初始化语句将会调用什么构造函数?记住,这种形式的初始化等效于下面的语句:

StringBad sailor  =  StringBad(sports);

因为sports的类型为StringBad,因此相应的构造函数原型应该如下:

StringBad( const  StringBad  & );

当我们使用一个对象来初始化另一个对象时,编译器将自动生成上述构造函数(称为复制构造函数,因为它创建对象的一个副本)。
现在我们不妨总结一下所谓的隐式成员函数,即C++自动提供了以下这些成员函数:

  • 默认构造函数,如果没有定义构造函数。
  • 复制构造函数,如果没有定义。
  • 赋值操作符,如果没有定义。
  • 默认析构函数,如果没有定义。
  • 地址操作符,如果没有定义。

现在我们来看看我们没有定义复制构造函数的情况下调用隐式复制构造函数将会出现什么情况。
从构造函数定义的代码片断可以看到,当中使用new操作符初始化了一个指针str,而隐式的复制构造函数是按值进行复制的,那么对于指针str,将会进行如下复制:

sailor.str  =  sports.str;

这里复制的不是字符串,而是一个指向字符串的指针!也就是说,我们将得到两个指向同一个字符串的指针!由此会产生的问题将不言而喻。当其中一个对象调用了析构函数之后,其str指向的内存将被释放,这个时候我们如果调用另一个对象,其str指向的地址数据会是什么?很明显将会出现不可预料的结果。

所以由此可见,如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,这被称为深度复制。因为默认的浅复制(或成为成员复制)仅浅浅的赋值指针信息。

我们再看以下代码片断,我们稍做修改:

StringBad headline1( " Celery Stalks at Midnight " );
StringBad knot;
knot 
=  headline1;

这里的最后一行将与以上例子有所区别,现在是将已有对象赋给另一个已有对象,这将会采取其他操作,即使用重载的赋值操作符。(我们需要知道的是:初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符)因为C++允许对象赋值,这是通过自动为类重载赋值操作符实现的。其原型如下:

Class_name  &  Class_name:: operator   =  ( const  Class_name  & );

它接受并返回一个指向类对象的引用。
与隐式的复制构造函数一样,隐式的对象赋值操作符也会产生同样的问题,即包含了使用new初始化的指针成员时,只会采用浅复制。所以我们需要使用同样的解决办法,即定义一个重载的赋值操作符来实现深度复制。

所以综上所述,如果类中包含了使用new初始化的指针成员,我们应该显式定义一个复制构造函数和一个重载的赋值操作符来实现其深度复制,避免由此带来的成员复制问题

参考书籍:C++PrimerPlus author:Stephen Prata

posted on 2006-09-28 14:33 爱上青菜的包子 阅读(1285) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理