2017-04-05 30 views
0

変数がC++のループ内で宣言されている場合、C++はループの各繰り返しで変数をリメイクしますか?つまり、別のnum変数のメモリを再割り当てしますか?したがって、ループが5回反復する場合、独自の固有の値を持つ5つの別々のnum変数が得られますか?その変数がループ内でのみ使用されるとしても、ループが開始する前に変数を宣言する方が良いでしょうか?たとえば、変数をカウンタまたはプレースホルダとして使用する場合はどうなりますか?C++はループ内で定義された変数をリメイクしますか?

// is this better code? 
// int num; 
for (int i = 0; i < 5; i++) { 
    int num; 
    // do stuff with num 
} 

答えて

4

numは、ループ内で定義される場合は、[はい、それは別の変数にループを実行するたびを表します。制御がその定義を通過するたびに、それは新たに初期化され(もしあれば)、ループの反復が終了するたびに破棄されます。

変数は通常、可能な限り狭い範囲で宣言する必要があります。したがって、numがある反復からその反復までその値を保持する必要がない場合、通常はループ内で定義する必要があります。 1つの反復から次の反復までその値を保持する必要がある場合は、その値をループ外で定義する必要があります。

初期化が高価な場合など、この文法的なベストプラクティスにはいくつかの例外があります。

4

コンパイラ変数が物理的に一度だけ割り当てられ、各ループ反復で再利用されるように、メモリ使用量を最適化します。しかし、一般的にYESのスコープ規則では、各ループの反復で変数の別のインスタンスを操作する必要があります。また、クラス/構造体のような複雑な型の場合は、各ループ反復で変数のコンストラクタとデストラクタを呼び出すことを意味します。

0

説明した状況では、C++標準では、変数の新しいインスタンスがループの始めに構築され、ループの最後に破棄されるように指定しています。

実際に何が起こるか、あなたがそれのぎこちなさに落ちるとき、ポイントのほかにあります。 C++の実装では、観測可能な結果がC++標準で指定されている限り、望みどおりに実装することができます。

ここでは、普通のガーデン品種intがあります。それは形式的に構築され、破壊されていますが、私が記述したように、変数が構築され、破壊されたときには、実際に何も起こりません。 C++では、新しく構築されたintをローカルスコープで特定の値に初期化する必要はありません。したがって、典型的なC++の実装では、この場合をメモリ内のいくつかのピジョンホールに割り当てるだけで、すべてのループの繰り返しにそれを使用するだけです。

しかし、このintを正式なコンストラクタで置き換えると、オブジェクトのコンストラクタがすべてのループ反復の最初に従順に呼び出され、オブジェクトのデストラクタが呼び出されます(または実行スレッドがループのスコープを離れるときに)素直に呼び出されます。

2

これは新しい変数です。あなたは簡単にこれをコンパイルするという事実によってそのことを自分自身を納得させることができます:それは本当に同じ変数だったら

for (int i = 0; i < 5; i++) { 
    const int num = i; 
    // do stuff with num 
} 

、どのように我々は、一定の変数に何か新しいものを割り当てていますか?

もっと効率的かどうかについては、C++に最適化コンパイラが非常に優れていることを覚えておく必要があります。スタック変数には実際の "コスト"はありません。単純な整数の割り当てには明らかに副作用がないため、コンパイラが同じ領域を再利用することは自明です。ループ外で変数を必要としない場合は、変数をループ内で宣言することをお勧めします。

https://gcc.godbolt.org/を使用して、最適化の有無にかかわらず、いくつかの小さな関数用に生成されたアセンブリを見ることをお勧めします。コンパイラが簡単に最適化できるものを感じるでしょう。

関連する問題