class str
{
int x;
public:
str(int i=0)
{
x=i;
cout<<"aa"<<endl;
}
str(str &y)
{
x=y.x;
cout<<"bb"<<endl;
}
str xy()
{
return *this;
}
};
void main()
{
str s=str(100);
str y=s.xy();
}当执行 str s=str(100);这行代码时 调用转换构造函数创建对象,屏幕打印"aa"。执行str y=s.xy() 时 先调用s.xy()函数, return *this复制一个当前的对象, 调用拷贝构造函数 屏幕打印出"bb"。 但是 用返回的对象初始化 y 时不是还是应该调用一次拷贝构造函数吗? 一共是两次调用拷贝构造函数。但是打印结果只是
"aa"
"bb"
说明只调用了一次拷贝构造函数.   我应该怎么样理解 请高手出来指教下.

解决方案 »

  1.   

    str y=s.xy();
    在声明时赋值, 对象只会调用一次构造你可以改成这样试试
    str y;
    y=s.xy();
      

  2.   

    楼主,了解一下RVO,以及VS怎么处理这个概念。
      

  3.   

    str y=s.xy();  //拷贝构造函数进行初始化了, 怎么会先去调用默认构造函数呢。str y;         //默认构造函数
    y=s.xy();      //这是赋值操作,operate =(), 如果没有重载操作符=的话,就不能这么赋值了
      

  4.   

      我的意思是 s.xy()在"return *this"时以经调用了拷贝构造函数.   str y=s.xy() 也就是 str y(s.xy) 应该再调用一次拷贝构造函数啊 就是把把 s.xy 返回的*this对象拷贝到 y中 , 但输出结果看好像只在调用s.xy() 时调用了一次构造函数   这是怎么回事
      

  5.   

    一、str(100)这种写法是调用构造函数创建匿名对象,所以输出aa,而在匿名对象创建之后就对s调用编译器为你准备的赋值操作符而不是拷贝构造函数,因为这里你不是用某个str类型的对象作为参数而是用100来调用str的构造函数,所以这里没有拷贝构造函数,因为赋值操作符是编译器生成的 ,所以没有任何输出;
    二、当执行 str y = s.xy()时,s.xy()返回匿名对象,然后用匿名对象作为拷贝构造函数的参数对y进行初始化。下面是四种肯定会调用拷贝构造函数的情形:
    这里b也是str类型的对象
    (1)str a(b);
    (2)str a = str(b);
    (3)str a = b;
    (4)str *pa = new str(b);
    相信你对(1)和(4)应该没有疑义,对于(2)中(3)均会调用拷贝构造函数,其中(2)中的str(b)这显然是对拷贝构造函数的调用,至于和(3),由于是初始化所以会调用拷贝构造函数。至于(2)中是先构造匿名对象,然后再用匿名对象作为参数来调用编译器为你准备的赋值操作符函数对a进行初始化,还是直接用b作为拷贝构造函数的参数来初始化a要取决编译器实现,但是你也看到了,不管是那种情况,均将调用拷贝构造函数。
      

  6.   

    str y=s.xy();  //拷贝构造函数进行初始化了, 怎么会先去调用默认构造函数呢。 str y;        //默认构造函数 
    y=s.xy();      //这是赋值操作,operate =(), 如果没有重载操作符=的话,就不能这么赋值了
      

  7.   

    str s=str(100);
    str y=s.xy();以上这些调用构造函数的过程如下:
    str() ---1 对应语句str s
    str(int i) ---2  对应语句str(100)
    str() ---3  对应语句 str y
    str(str &y) ---4 对应语句 y=s.xy()