5
class test{

public:

    int data;
    test(const test& ){cout<<"INSIDE COPY CON "<<endl;}
    test(int val = 0) : data(val){ cout<<"INSIDE CON "<<endl; }

    test testfun(const test& obj)
    {
        cout<<"data : "<<data<<endl;
        //test test3(this->data + obj.data);
        //cout<<"test3 :"<<test3.data<<endl;
        //return test3;   //This will work only if return type is changed to const ref
        return test(data + obj.data); 


    }
};

int main()
{

    test testO1(1);
    test testO2(2);
    test testO3 = testO1.testfun(testO2);

    cout<<testO3.data<<endl;


    getchar();


}

出力:

INSIDE CON

INSIDE CON

data : 1

INSIDE CON

3

returnステートメントでコンストラクターが呼び出されるとどうなりますか? 私は値で返すことができ、それが機能するので、一時的な場所ではないと思います. または、オブジェクトを一時的に作成し、コピー コンストラクターを使用して値をコピーします。その場合、コピー コンストラクター内の印刷が印刷されないのはなぜですか。

4

3 に答える 3

10

一時オブジェクトを作成し、それを戻り値にコピーします。

ただし、効率を高めるために、C++ ではコピー コンストラクター (または C++11 の移動コンストラクター) の呼び出しを省略できるため、コピー コンストラクターの副作用が発生することに依存するべきではありません。

戻り値の最適化速度が必要ですか?を参照してください。値渡し

于 2012-06-08T00:41:09.180 に答える
7

あなたは鋭い質問をします。

どうするかは、コンパイラと関連するツールチェーン次第ですが、基本的なパターンは次のとおりです。を呼び出す前testfun()に、呼び出し元 [ main()、あなたの例では] はスタックにスペースを予約test03します。次に、 のアドレスを に渡しtest03ますtestfun()

関数は、呼び出し元が指定したアドレスにオブジェクトをtestfun()配置する必要があります。test関数に return ステートメントが 1 つしかない場合は、呼び出し元が提供するストレージを自由に使用して戻り値を構築できます。独自のストレージを使用する必要はありません。を使用できますmain()

さて、この戦略は常に機能するとは限りません。testfun()関数 likeに 2 つの別個の return ステートメントがあり、そのうちの 1 つまたは両方が一時オブジェクトではなく名前付きオブジェクトを返す場合、通常は失敗します。その場合、コンパイラは不要なコピー オン リターンを強制的に実行します。ただし、より一般的なケースはあなたのケースに似ておりtestfun()、戻り値を必要な場所に直接構築するだけですmain()。この場合、実際のコピーは行われません。

したがって、このような場合に戻り時にコピー コンストラクターを呼び出すかどうかを決定するのはコンパイラ次第です。

于 2012-06-08T00:48:12.810 に答える