4

VC2010 を使用してデバッグ モードでビルドすると、このコピー コンストラクターが呼び出されない理由がよくわかりません。

class SomeClass
{
public:
    SomeClass(int meaningless){}

    SomeClass(const SomeClass& sc)
    {
        cout << "Copy Constructor invoked!" << endl;
    }
};

int main()
{
    SomeClass test(SomeClass(9999));  // Copy constructor not invoked. 
}

値を返さないので、これは RVO とは関係ないと思います。

さらに興味深いことに、コピー コンストラクターをプライベートにすると、コンパイラーはコピー コンストラクターを省略してもコンパイルすらしません。

4

2 に答える 2

5

これは、コンパイラによって行われる最適化です。言語仕様によると、コンパイラは可能な限りコピー コンストラクターの呼び出しを省略できます。

アクセス可能なコピー コンストラクターは、実際には呼び出されませんが、セマンティック チェックのみに必要です。セマンティック チェックは、最適化のかなり前に行われます。

ただし、-fno-elide-constructorsGCC でオプションを付けてコンパイルすると、copy-elision は実行されず、copy-constructor が呼び出されます。GCCのドキュメントによると、

-fno-elide-constructors

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

MSVC10 では、/Odを使用できます。これは、MSDN によれば、プログラム内のすべての最適化をオフにします。

注: ウィキペディアにコピー省略に関する記事があります。

于 2012-04-18T01:00:34.527 に答える
4

C++11 標準、§12.8.31 によると:

copy elisionと呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。

…</p>

  • 参照にバインドされていない一時クラス オブジェクトが同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、コピー/移動操作は、一時オブジェクトを省略されたオブジェクトのターゲットに直接構築することによって省略できます。コピー/移動

C++ では一時オブジェクトに多くの余裕があり、コンパイラはそれらを削除する際に非常に積極的になります。オブジェクトに何らかの形で独自の有効期間がある場合、コピー コンストラクター呼び出されることになります。

ただし、コピー コンストラクターのアクセス修飾子をチェックすることは間違いなく期待できますが、そうすべきではない引数を確認できます (結局のところ、コピー コンストラクターを呼び出していないだけです)。しかし、コピーの省略はオプションであるため、これはおそらくあまり良い方法ではありません。

于 2012-04-18T01:05:24.993 に答える