5

次のコードは、デストラクタを 4 回呼び出します。

#include<iostream>
using namespace std;

class A{
   public:
   A(){cout<<"A"<<endl;}
   ~A(){cout<<"~A"<<endl;}
   A f(){cout<<"F"<<endl; A b; return b;}
};

int main(){
   A a,b;
   b=a.f();
}

出力:

A
A
F
A
~A
~A
~A
~A

誰か説明してもらえますか?デストラクタの呼び出しは 3 つだけにすべきだと考えていました。

4

6 に答える 6

8

には 2 つのオブジェクトがあるため、それらのためmain()にデストラクタが2回呼び出されます。の 1 つのオブジェクトf()なので、デストラクタはそのためだけに1回呼び出されます。合計 3 回 (予想どおりですが、読み進めてください...)

から戻るときに作成される一時オブジェクトに対して、4 回目のデストラクタが呼び出されfます。これは、RVO がまったくない場合にのみ発生する可能性があります。RVO はコンパイラの選択です。つまり、最適化する場合としない場合があります。この言語は、RVO を保証するものではありません。

とにかく、最適化レベルを上げるだけです。多くても 3 つのデストラクタ呼び出しのみが表示されると確信しています。

于 2012-02-12T10:39:05.230 に答える
3

main:A a,b;には 2 つのオブジェクトがあり、 function f():の本体には 1 つのオブジェクトA b;があり、コピーされる一時オブジェクトとそのコピーが に格納されbます。

関数の本体に戻るbと、最初にコピーが作成され、次にローカルが破棄され、次にコピーがメインで宣言bされた変数に割り当てられ、次にこのコピーが破棄されます。b

次の行をクラスA定義に追加して、自分自身を確認してください。

A(const A&) { cout << "copying" << endl; }

Named Return Value Optimizationを使用すると、コンパイラは冗長な Copy コンストラクターと Destructor 呼び出しを排除しようとしますb。これは、コピーが作成されることなく、関数のローカルが main のf()変数に割り当てられることを意味します。bしたがって、RVO / NRVO では、3 つのオブジェクトのみが作成されます。

あなたの場合、RVOなしでこのコピーを破壊しないようにする方法はありますが:

A a;
A b = a.f();

この場合、関数の戻り値のコピーf()が作成され、変数として保存されますb。これは、代入演算子が呼び出されず、2 つのオブジェクトのみが main: で作成され、によって返されるaのコピーが作成されることも意味します。bf()

お役に立てれば。

于 2012-02-12T10:54:12.647 に答える
1

あなたのコンパイラはそれを最適化しませんでした。最適化を有効にしてコンパイルしましたか?

gcc でコンパイルされた同じコードの出力を次に示します。

A
A
F
A
~A
~A
~A
于 2012-02-12T10:38:53.183 に答える
1

のインスタンスの非表示の作成と破棄が 1 つありAます。 function から戻るとf()、 object の一時的なコピーbが作成されます。に割り当てられてからb破棄main()されます。

于 2012-02-12T10:41:23.560 に答える
0

RVO の発生に依存することはできません。そのため、機能ロジックをデストラクタまたはコピー コンストラクタ内に配置しないでください (そうです、それらも省略できます)。

戻り値の最適化は、標準で許可されているだけで、強制されていません。

最適化または O2 を使用しない場合、私も 4 つのデストラクタ コールを取得します。

完全に最適化すると-Ox-3しか得られません。

于 2012-02-12T10:41:03.010 に答える
0

関数が戻ると、ローカル変数 infが一時変数にコピーされます。そのため、4 つのデストラクタ呼び出しがあります。(コピー操作は、A(A&)デフォルトのコンストラクターではなくコピー コンストラクターを呼び出すA()ため、3 つAの s.)

于 2012-02-12T10:45:37.333 に答える