20

重複の可能性:
コピーの省略と戻り値の最適化とは何ですか?

次のコードでコピーコンストラクターが呼び出されない理由を理解するのに苦労しています。

#include <iostream>

class Test
{
public:
  Test(int){std::cout << "Test()" << std::endl;}
  Test(const Test&){std::cout << "Test(const Test&)" << std::endl;}
};

int main()
{
  // Test test;
  Test test2(Test(3));

  return 0;
}

コンストラクターのみが呼び出され、コピーコンストラクターが呼び出されない理由を誰かが説明できますか?
ありがとう。

4

3 に答える 3

25

これはコピーの省略と呼ばれます。
コンパイラーはこの最適化を行うことができます。標準では保証されていませんが、商用コンパイラは可能な限りこの最適化を実行します。


標準リファレンス

C ++ 03 12.8.15:

[...]このコピー操作の省略は、次の状況で許可されます(複数のコピーを削除するために組み合わせることができます)。

[...]

  • 参照(12.2)にバインドされていない一時クラスオブジェクトが同じcv-unqualifiedタイプのクラスオブジェクトにコピーされる場合、省略されたコピーのターゲットに一時オブジェクトを直接構築することにより、コピー操作を省略できます。

gccの場合のように、マニュアルページからいくつかのコンパイラ設定を使用してこの最適化を無効にすることができます。

-fno-elide-constructor

C ++標準では、同じタイプの別のオブジェクトを初期化するためにのみ使用される一時オブジェクトの作成を実装で省略できます。このオプションを指定すると、その最適化が無効になり、G++はすべての場合にコピーコンストラクターを呼び出すように強制されます。

ただし、これを使用すると、コードが異なるコンパイラ間で移植できなくなります。

于 2013-01-04T09:22:47.053 に答える
11

これは、コンパイラによって実行される最適化が原因です。コンパイラーはそのような最適化を実行することを許可されていますが、それは必須ではないため、保証されていません。

コピーコンストラクターは最終的には呼び出されませんが、意味的にはアクセス可能である必要があることに注意してください。つまり、コピーコンストラクタを作成するprivateと、コードはコンパイルされません!! これは、セマンティックチェックが最適化フェーズのかなり前に行われるためです。つまり、コンパイラは最初にコピーコンストラクタがアクセス可能かどうかをチェックします。アクセス可能である場合は、コピー構築が省略される最適化フェーズのみが行われます。

于 2013-01-04T09:22:59.857 に答える
0

他の人がすでによく述べているように、これはコンパイラからの最適化によるものです。

私はそれをチェックしていませんが、おそらく最適化を使用してコードをコンパイルし、アセンブラーコードを確認せずにコンパイルすることができます。次に、いくつかの違いも明確に確認する必要があります。

于 2013-01-04T09:41:44.880 に答える