r2100

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  8 Posts :: 9 Stories :: 2 Comments :: 0 Trackbacks

常用链接

留言簿(3)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜


对于C++类:显示地写出拷贝构造函数,重载赋值操作符和析构函数是良好的习惯,但在写构造函数时需要注意一些容易的错误,如下面的代码:

 

#include <iostream>

using namespace std;

 

class M{

public:

    M()
{}

    M(
const M &m){

       cout
<<"copy construtor"<<endl;

       
operator =(m);

    }


    M 
operator =(const M &m){   //问题出在此处

       cout
<<"operator ="<<endl;

       
return *this;

    }


}
;

 

int main() {

    M m1;

    M m2;

    m2
=m1;

    
return 0;

}

 

在下面三种情况下会调用拷贝构造函数:

(1)用一个已经实例化了的该类对象,去实例化该类的另外一个对象;

(2)用该类的对象传值的方式作为一个函数的参数;

(3)一个函数返回值为该类的一个对象。

特别地,对于语句 M m;  M mm=m; 属于(1)情况,即语句M mm=m;调用的是拷贝构造函数,而不是构造函数。

 

但在重载=操作符时,返回值不是引用类型将导致程序运行出现严重问题。即如果出现上面会调用拷贝构造函数的三种情况之一,或者使用=操作符时,拷贝构造函数和operator =将循环递归调用,导致程序出现死循环。原因是拷贝构造函数和operator =之间不断地重复调用。

解决办法:将operator =的返回类型改为引用类型M&,此时调用operator =时不会去调用拷贝构造函数。

 

还有,若要写clone时,若通过下面的方式:

 

    M clone(){

       cout
<<"clone"<<endl;

       
return *this;

    }


前提是拷贝构造函数不能调用clone来完成拷贝,否则出现上面同样的问题,下面的代码就会出现这样的问题

   

M(const M &m){

       cout
<<"copy construtor"<<endl;

       clone();

    }


总之,在写这些函数时,要特别留意彼此的调用关系。

以下是我的惯用写法:

(A)对于拷贝构造函数和重载=操作符

  

  M(const M &m){

       cout
<<"copy construtor"<<endl;

       
operator =(m);

    }


    M
& operator =(const M &m){  //问题出在此处

       cout
<<"operator ="<<endl;

       
/* 此处写上成员数据的拷贝 */

       
return *this;

    }


这里写成了inline函数,只是方便说明问题,其实不必非要这么写,可以采取先声明,后定义的常规方法。

(B)对于clone函数

声明:  virtual M clone();   //考虑继承时的多态

定义:  

M M::clone(){

       cout
<<"clone"<<endl;

       
//将在调用处直接调用构造函数,效率高,避免返回局部变量,更安全

       
return M();

    }



 

posted on 2011-04-06 13:18 r2100 阅读(686) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理