6

重複の可能性:
ブロックを使用して C++ の変数のスコープを管理できますか?

次のような C++ コードを見つけました。

int main(void) {

  int foo;
  float qux;
  /* do some stuff */

  {
    int bar;
    bar = foo * foo;
    qux = some_func(bar);
  }

  /* continue doing some more stuff */
}

最初は、元の作成者がいくつかの関連する変数をグループ化するために中括弧を使用しているのではないかと考えていましたが、設計中のシステムには十分なメモリがないため、作成者はバーのスコープを解決し、変数をin は、囲んでいる ( foo の) スコープ全体で使用するのではなく、離れていきます。

これを行う理由はありますか?これは必要ではないように思えますが、最新のコンパイラはこれを不要にしますか?

4

6 に答える 6

10

これは必要ではないように思えますが、最新のコンパイラはこれを不要にしますか?

はい、最新のコンパイラは、このような場合にメモリ使用量を最適化します。スコープを追加しても、コードが高速になったり、メモリ効率が向上したりすることはありません。

ただし、プログラムの動作が変わるため、副作用のあるデストラクタを使用してオブジェクトを最適化することはできません。したがって、これはそのようなオブジェクトに対して行うのが理にかなっています。

これを行う理由はありますか?

関連するコードをグループ化すると便利です。中括弧内で宣言された変数は他の場所では使用されないことを知っていると非常に役立ちます。

于 2012-11-03T03:22:43.747 に答える
4

1 つのメソッドでこれを複数回行うと、コンパイラによっては、そのメソッドが占有するスタック スペースが少なくなる可能性があります。リソースが限られている場合は、マイクロコントローラーを使用している可能性があり、そのコンパイラーは常に x86 コンパイラーほどフル機能ではありません。

また、(int と float ではなく) 完全なクラスでこれを行うと、デストラクタが呼び出される場所を制御できます。

class MyClass;

int main(void) {

    int foo;
    float qux;
    /* do some stuff */

    {
        MyClass bar;
        qux = some_func(bar);
    } // <-- ~MyClass() called here.

    /* continue doing some more stuff */
}
于 2012-11-03T03:23:08.243 に答える
4

C/C++ の場合、名前間の競合を制限しようとすることができます (非常に長い関数を持つため、この方法で変数をスコープする必要があるのは悪い考えです...) つまりbar、同じ関数に複数ある場合は、この方法でそれらをスコープするよりも互いに衝突/オーバーライドしないようにします。

通常、関数内のスコープはスタック割り当てサイズに影響しません。スタックは、スコープに関係なく、すべてのローカル変数に事前に割り当てられます。

于 2012-11-03T03:24:27.320 に答える
3

コードが本当にあなたが示したようなものである場合、それはおそらくほとんど無意味です. 私が見たほとんどのコンパイラは、関数への入り口ですべてのローカル変数にスペースを割り当て、関数からの出口でそれを解放します。ただし、他にもいくつかの可能性があります。

あなたが示しbarたものが何らかのクラスタイプのオブジェクト(特にデストラクタを持つもの)であった場合、デストラクタは、スペースが後で解放されなかったとしても、スコープから出るときに実行されます。

もう 1 つの可能性は、実際には2 つの内部スコープがあったことです。

int main() { 
// ...

    { 
        // some variables
    }

// ...

    {
        // other variables
    }
}

この場合、ローカル変数のスペースはmain--へのエントリで割り当てられます、(通常) 同じスペースを共有します。つまり、割り当てられるスペースは、2 つのうち大きい方を収容するのに十分ですが、(通常)のスコープですべての変数を定義した場合に使用するように、2 つの合計にはなりません。some variablesother variablesmain

于 2012-11-03T03:22:52.300 に答える
2

bar のスコープを解決し、それを囲む (foo の) スコープ全体で使用するのではなく、in を含む変数をすべて削除するという意図

これは、(重要ではなくレガシーな) 理由の 1 つかもしれません。もう 1 つの理由は、このスコープ内で非常に小さな機能 (関数内の関数のようなもの) を持つために使用され
ていることを読者に伝えるためです。int barその後は使用しませんbar

あなたのコードは以下と同等です:

  inline void Update (int &foo, float &qux)
  {
    int bar = foo * foo;
    qux = some_func(bar);
  }
  int main ()
  {
    ...
    Update(foo, qux);
    ...
  }

ほとんどのコンパイラは、Update()内部への呼び出しを最適化しmain()、インライン化します。これにより、投稿したものと同様のものが生成されます。

于 2012-11-03T03:24:13.540 に答える
2

出力を最適化するのではなく、プログラマーを支援することを意図している可能性があります。最新のコンパイラーは確かに、一時変数が一度しか使用されないことを確認できるほど賢いからです。

一方、プログラマーにとっては、論理的な分離を追加します。これは、「これらの変数はこのコードにのみ必要である」ことを意味し、おそらく「このコードはこの関数の他のコードに影響を与えない」ことも意味します。

于 2012-11-03T03:24:35.273 に答える