ループ内のローカルオブジェクトのデストラクタは、次の反復の前に呼び出されることが保証されていますか?


11

ループがあり、このループ内で新しいスタック変数を作成すると(ヒープ上に割り当てず、ループ本体内で宣言された変数を保持する変数ではありません)、このオブジェクトのデストラクタは、次の反復が始まる前に呼び出されることが保証されます。コンパイラによるループの展開はそれについて何かを変更しますか?


1
ループの展開自体は、実行の順序を変更しません。ただし、ループの並列化でこれを行うことができます。
Adrian Mole、

回答:


8

からn4800

§6.3.3 ブロック範囲

ブロック(8.3)で宣言された名前は、そのブロックに対してローカルです。ブロックスコープがあります。その潜在的なスコープは、宣言の時点(6.3.2)で始まり、そのブロックの終わりで終わります。ブロックスコープで宣言された変数はローカル変数です。

§10.3.6 デストラクタ

オブジェクトが作成されたブロックが終了すると、デストラクタが暗黙的に呼び出されます[...](8.7)

§4.1.1 抽象マシン

この規定は、「as-if」ルールと呼ばれることもあります。これは、実装がこのドキュメントの要件を無視できるということです。プログラム

[エンファシス鉱山]

あ、はい。変数がループの終わり(ブロック)でスコープ外になるため、プログラムの動作を監視している人が知る限り、そのデストラクタが呼び出されます


1
デストラクタが呼び出されるときについては何もありません。
スターク

2
@stark彼らがこれを行うことができるのは、as-ifルールです。この規格では、抽象マシンの動作のみを指定しています。ここで回答のすべての詳細に入る必要があるかどうかはわかりません。
Max Langhof

2
@starkこれはIMOで、質問とは無関係です。デストラクタはインライン化される可能性があるため、まったくcall編集されない場合もあります。または、それらが実質的に(as-ifルールで)何もしない場合、生成されたそのようなデストラクタのアセンブリがない可能性があります。
Daniel Langr


2
@starkどこにが定義されてますか?このディスカッションは質問とは無関係です。この問題について、別の質問をすることができます。
Daniel Langr

8

はい。変数を宣言する「ブロック」を検討すると、視覚化するのが簡単になります。ループはそれ自体がブロックであり、閉じ括弧に達すると、次の反復の前に、ループで宣言されている自動ストレージ変数のすべてのデストラクタが呼び出されます。

コンパイラーによるループのアンロールは、それについて何かを変えるのでしょうか?

経験則として、コンパイラーが最適化するものについては考えないでください。最適化するために何をしても、プログラムの動作を保証する必要があるためです。その場合、ループの展開は、それが起こってもその効果に何も変更しません。


2
経験則+1、コードを書くとき、コンパイラの内部について心配するべきではありません。同じ精神で何かを私の答えに追加するつもりでしたが、今ではすでにそこにあります
idclev 463035818

コピー削除とRVOはプログラムの動作を変更しますね。
Jean-BaptisteYunès19年

@Jean-BaptisteYunès彼らは可能性がありますが、標準でも許可されています[class.copy.elision]
ChrisMM

中括弧のペアだけではありません。あなたは書くことができfor(...) X x{};xオブジェクトは各反復で構築され、破壊されます。ライブデモ。関連する標準セクションはstmt.iter / 2です。
Daniel Langr

@DanielsaysreinstateMonica§9.5.2によると、これは[stmt.iter]完全に同等です(強調文):「反復ステートメント内のサブステートメントが単一ステートメントであり、複合ステートメントではない場合、複合ステートメントに書き換えられたかのようになります。元のステートメント。 " 本質的に、単一のステートメントで中括弧がある場合とない場合は、まったく同じことを意味し、中括弧は暗黙的です。わかりやすくするために省略しました。
JBL、

2

デストラクタはすべての反復で呼び出されます。したがって、場合によっては、ループ内ではなくループ外で変数を宣言する方が高速です。次の場合を想定します。

std::string temp;
for(int i = 0; i < 10; ++i){
    temp = arr[i];
    doSomething(temp);
}

ループの使用時に、デストラクタは呼び出されません。それは単に上書きしますtemp

しかしstd::string temp = arr[i]、コンストラクタを使用すると、反復ごとにデストラクタが呼び出されます。非常に頻繁に実行されるループがある場合、これは少しランタイムを追加すると思います。


デストラクタが呼び出されるかどうかは、パフォーマンスの問題だけではないことに注意してください。RAIIタイプがある場合、すべての反復でデストラクタが呼び出されるように具体的に指定します
idclev 463035818

それが本当かどうかわからない。tempが新しい値で再割り当てされたときに、コンテンツ 'temp'のデストラクタが前の反復から保持しているのではないですか?
user1282931

私も100%確実ではありません。何か間違ったことを見つけたら、私の答えを訂正してください。:)
Julian Schnabel


0

もちろん、dtorは反復の終わりに呼び出され、ループのアンロールはこの動作を変更するべきではありません。他の最適化(最適化はプログラムの動作を変更するべきではありません)と同じです。 。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.