4

重複の可能性:
デストラクタが一度だけ呼び出されたのはなぜですか?

以下のコードを考えると、gccでの出力を理解できません。2つのオブジェクトが作成および破棄されることを期待していますが、代わりにコンストラクタとデストラクタへの呼び出しが1つだけ表示されます。ここで何が起こっているのですか?

#include <string>
#include <iostream>

struct Huge{
        Huge() { std::cout << "Constructor" << std::endl; }
        Huge(Huge const &r) { std::cout << "Copy Constructor" << std::endl; }
        ~Huge() { std::cout << "Destructor" << std::endl; }
};

Huge g() {
        std::cout << "Entering g" << std::endl;
        Huge temp;
        std::cout << "Exiting g" << std::endl;
        return temp;
}

int main(){
        Huge h2(g());
        std::cout << "Before leaving main" << std::endl;
}

g ++(4.4)でのこのコードの出力は次のとおりです。

gを入力する

コンストラクタ

gを終了します

メインを離れる前に

デストラクタ

4

2 に答える 2

6

はい、これはNamed Return Value Optimizationによるコピー省略です。

C++ 標準では、コピー コンストラクターに副作用がある場合でも、return ステートメントから生じるコピー操作を実装で省略することができます。

参照:

C++03 標準:
12.8 クラス オブジェクトのコピー:

#15

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

— クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性の自動オブジェクトの名前である場合、コピー操作は自動オブジェクトを構築することによって省略できます。オブジェクトを関数の戻り値に直接

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

于 2012-01-17T06:27:30.057 に答える
1

C++ では、あなたのような場合に余分なオブジェクトの作成とコピーを避けることができます。これは、名前付き戻り値の最適化として知られています。要点は、返された後はオブジェクトtempが消えてしまい、コピー コンストラクターのセマンティクスは、元のオブジェクトとまったく同じコピーを作成する必要があることを確実に知っているということです。

実際には、ここで2 つの最適化が行われていることに注意してください。最適化を行わないと、オブジェクトtempは最初に in の戻り値にコピーされ、g次に戻り値が in にコピーさh2mainます。名前付きの戻り値の最適化は、コピーを戻り値に省略します。戻り値が一時オブジェクトであるため、戻り値からへのコピーh2は省略されます。ここでも、コピーの作成は省略される場合があります。

他の最適化とは異なり、これらの最適化は、(テスト プログラムのように) 観察可能な動作を変更する場合でも許可されることに注意してください。これは、そうでなければ、これらの最適化が違いを生まない多くの場合に実行できなかったからです (実際、デバッグ出力を除いて、これは適切に作成されたプログラムでは決して違いを生むべきではありません)。省略は観察可能な動作を変更しません。一方、コピーを手動で削除する方法はないため、コンパイラが自動的に削除できることが重要です。

最終的に何が起こるかというと、return ステートメントの時点ですでに正しい値が含まれているように、オブジェクトtempが占有するスペースに直接作成されるということです。つまり、最適化により、とは実際には同じオブジェクトです。h2h2temph2

于 2012-01-17T06:30:41.240 に答える