3

私はこのコードを書きました:

    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)

最初の 2 行は問題ありません。しかし、3 行目と 4 行目は、X(X&) を 2 回呼び出していることを示しています。copy(X a) には「X a」が 1 つだけ含まれています。X(X&) が 2 回呼び出されるのはなぜですか?

4

2 に答える 2

6

なぜX(X&)2 回呼び出される可能性があるのでしょうか。

関数呼び出しの場合:

loc2 = copy(loc);    

copy(loc);コピー コンストラクターを 2 回呼び出します。

  1. loc関数に渡される引数のコピーを作成します。
  2. 戻りオブジェクトのコピーを作成しますa

C/C++ では、関数への引数はデフォルトで値渡しされます。したがって、実際の引数ではなく、渡されたオブジェクト/変数のコピーが関数呼び出しで受信されます。このコピーは、コピー コンストラクターを呼び出すことによって作成されます。
また、copy()関数は再び値によって戻り、その結果、コピー コンストラクターが呼び出されます。

場合によっては、コンパイラがコンストラクターをコピーしてオブジェクトをインラインで構築する呼び出しを省略 (削除) する可能性があることに注意してください。この現象はCopy Elision として知られています。一般に、コピーの回数に基づいて副作用を生成するコードは記述しないでください。コンストラクターが呼び出されています。

于 2012-10-05T04:27:13.510 に答える
1

「return a」が実行されると、戻り値の型が X (X& ではない) であるため、型 X のオブジェクトのコピーが作成されます。(X& だったら - それもエラーだったでしょう - コピー関数の仮引数 "a" はローカル スコープの変数です)

于 2012-10-05T04:58:02.337 に答える