4

次のコードでは、2つの異なるメモリ位置を出力します。私は価値によって戻ってきているので、これは私にとって理にかなっています。

#include <iostream>

using namespace std;

class Foo {
public:
        Foo () {}
//      Foo (const Foo &) { cout << "Copy con" << endl; }
};

Foo test () {
        Foo foo;
        cout << &foo << endl;
        return foo;
}

int main () {
        Foo foo = test();
        cout << &foo << endl;
}

ただし、上記のコードでコピーコンストラクターのコメントを解除して再度実行すると、同じメモリ位置が2回出力されます。なんで?「Copycon」はまったく出力されないので、コピーコンストラクターが呼び出されていないことがわかります。コピーコンストラクターが存在するだけで、呼び出されなくても、ある種の最適化が行われるようです。

GCC4.6.3で「g++-Walltest.cpp-otest」をコンパイルしています。

4

1 に答える 1

2

これは戻り値の最適化の結果です。基本的に、コピー コンストラクターには副作用がありますが、コンパイラーは return ステートメントから生じるコストのかかるコピー操作を省略します。

この背後にある理由は、複雑なオブジェクトを返すにはコストがかかるためです。コピーに時間を浪費する代わりに、コンパイラは呼び出し元のスタック フレームに隠しオブジェクトを秘密裏に作成し、その隠しオブジェクトへの参照を呼び出された関数に渡します。関数の戻り値は、その隠しオブジェクトに直接コピーされます。

C++ 標準はこれを明示的に述べています (ISO-IEC 14882:2011 12.8 para. 31):

特定の基準が満たされている場合、オブジェクトのコピー/移動コンストラクターおよび/またはデストラクタに副作用がある場合でも、実装はクラス オブジェクトのコピー/移動構築を省略できます。

于 2012-09-12T11:11:58.533 に答える