6

私は単に次のようなクラスを作成しました:

class GreatClass
{
public:
    GreatClass(){cout<<"Default Constructor Called!\n";}
    GreatClass(GreatClass &gc){cout<<"Copy Constructor Called!\n";}
    GreatClass(const GreatClass &gc){cout<<"Copy Constructor (CONST) Called!\n";}
    ~GreatClass(){cout<<"Destructor Called.\n";}
    GreatClass& operator=(GreatClass& gc){cout<<"Assign Operator Called!";return gc;}
    const GreatClass& operator=(const GreatClass& gc){cout<<"Assign Operator (CONST) Called!";return gc;}
};

GreatClass f(GreatClass gc)
{
    return gc;
}

main() 関数には、次の 2 つのバージョンがあります。

バージョン #1:

int main()
{
    GreatClass g1;
    GreatClass G = f(g1);
}

バージョン #2:

int main()
{
    GreatClass g1;
    f(g1);
}

それらはすべて同じ出力を生成します。

Default Constructor Called!
Copy Constructor Called!
Copy Constructor Called!
Destructor Called.
Destructor Called.
Destructor Called.

f(g1)に割り当てているときに何も起こらない理由がわかりませんG。この時点で呼び出されるコンストラクターまたはオペレーターは?

ありがとう。

4

1 に答える 1

13

コンパイラの実装では、特定の場合にコピー コンストラクターの呼び出しを省略/削除することが許可されています。指定した例は、そのようなシナリオの良い使用例です。一時オブジェクトを作成して宛先オブジェクトにコピーする代わりに、オブジェクトが宛先オブジェクトに直接作成され、コピー コンストラクターの呼び出しが削除されます。

この最適化は、戻り値の最適化によるコピー省略として知られています。

また、C++11 では、右辺値参照による移動セマンティクスが、コピー セマンティクスの代わりに作動する可能性があります。移動セマンティクスを使用しても、コンパイラは RVO を自由に適用できます。

于 2013-07-01T16:59:20.553 に答える