为什么X(X&)可以被调用两次?

时间:2012-10-05 04:24:20

标签: c++ constructor destructor

我写了这段代码:

    struct X{
        int val;

        void out(const string& s, int nv)
            {cerr<<this<<"->"<<s<<": "<<val<<"("<<nv<<")\n";}

        X() {out("X(int)",0); val=0;}
        X(int v){out("X(int)",v); val=v;}
        X(const X& x){out("X(X&)",x.val); val=x.val;}
        X& operator=(const X& a)
            {out("X::operator=()",a.val); val=a.val; return *this;}
        ~X() {out("~X()",0);}
    };

    X copy(X a) {return a;}

    int main{
        X loc2;
        X loc(5);
        loc2 = copy(loc);
        return 0;
    }

输出为此(在VS2010中):

003BFAA0->X(int): -858993460(0)
003BFA94->X(int): -858993460(5)
003BF964->X(X&): 723486321(5)
003BF994->X(X&): -858993460(5)
003BF964->~X(): 5(0)
003BFAA0->X::operator=(): 0(5)
003BF994->~X(): 5(0)

前两行很好。但第三和第四行表明它调用X(X&amp;)两次。副本(X a)中只有一个“X a”。为什么X(X&amp;)可以被调用两次?

2 个答案:

答案 0 :(得分:6)

  

为什么X(X&)可以被调用两次?

使用函数调用:

loc2 = copy(loc);    

copy(loc);调用复制构造函数两次:

  1. 创建传递给函数的参数loc的副本。
  2. 创建返回对象a的副本。
  3. 在C / C ++中,默认情况下,函数的参数是 按值传递 。所以不是实际的参数,而是在函数调用中接收传递的对象/变量的副本。这个副本是通过调用复制构造函数创建的。
    您的copy()函数 再次按值返回 ,导致调用复制构造函数。

    请注意,在某些情况下,编译器可能会删除(删除)对复制构造函数的调用并构造内联对象,这种现象称为复制Elision 。通常,您不应该编写任何代码根据复制构造函数的调用次数产生副作用。

答案 1 :(得分:1)

当执行“return a”时,会创建X类型对象的副本,因为返回类型为X(不是X&amp;)。 (如果它是X&amp; - 它也会出错 - 复制函数的正式参数“a”是具有局部范围的变量)