6

次の2つの機能があります。

Class foo(Class arg)
{
    return arg;
}

Class bar(Class *arg)
{
    return *arg;
}

ここで、foo(arg) のみを呼び出すと、もちろんコピー コンストラクターが 2 回呼び出されます。bar(&arg) を単独で呼び出すと、一度だけ呼び出されます。したがって、私は期待します

foo(bar(&arg));

ここでは、コピー コンストラクターが 3 回呼び出されています。ただし、まだ 2 回しか呼び出されません。何故ですか?コンパイラは別のコピーが不要であることを認識していますか?

前もって感謝します!

4

1 に答える 1

6

コンパイラは別のコピーが不要であることを認識していますか?

確かにそうです。コンパイラは、コピー/移動省略を実行しています。これは、いわゆる「as-if」ルールの唯一の例外であり、コンパイラー (例のような状況では) は、クラスのコピーまたは移動コンストラクターへの呼び出しを省略できます。効果。

C++11 標準のパラグラフ 12.8/31 によると:

特定の基準が満たされると、コピー/移動操作用に選択されたコンストラクターおよび/またはオブジェクトのデストラクタに副作用がある場合でも、実装はクラス オブジェクトのコピー/移動構築を省略できます。このような場合、実装は、省略されたコピー/移動操作のソースとターゲットを、同じオブジェクトを参照する 2 つの異なる方法として扱い、そのオブジェクトの破棄は、2 つのオブジェクトが削除された時点のいずれか遅い方の時点で発生します。最適化なしで破壊されました。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。

returnクラスの戻り値の型を持つ関数内のステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性自動オブジェクト (関数または catch-clause パラメーター以外) の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます

— [...]

— 参照 (12.2) にバインドされていない一時クラス オブジェクトが同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、一時オブジェクトを省略したコピー/移動の対象

— [...]

GCC では、-fno-elide-constructorコンパイル フラグを使用してこの最適化を抑制し、コピー省略が発生しない場合にコンパイラがどのように動作するかを確認できます。

于 2013-05-12T12:00:48.553 に答える