独自の中括弧内のforループ


117

私はこのforループのレイアウトに遭遇しました:

#include <iostream>
int main()
{
    {
        for (int i = 0; i != 10; ++i)
        {
            std::cout << "delete i->second;" << std::endl;
        }
    }

    {
        for (size_t i = 0; i < 20; ++i)
        {
            std::cout << "delete m_indices[i];" << std::endl;
        }
    }
    return 0;
}

この余分なブレースの層が何のためにあるのかと思っていましたか?これは、コードベースで数回表示されます。


47
あなたが投稿したコードスニペットでは完全に
不要

25
このコードで使用されているコンパイラは何ですか?具体的にはVS 6が使用されましたか?
UKMonkey 2018年

5
@EdNormanを編集すると、より明確になります。正解はUKMonkeyによって提供されたもののようです。最新のC ++コンパイラを使用すると、中括弧を簡単に削除できます。
Jabberwocky

8
あるいは、コードを生成することもできます(Rhapsodyを
使い始めた

4
考えられる理由の1つは、コードにOpenMPパラレルディレクティブがあった(または将来持つ予定がある)場合です。
jamesqf 2018年

回答:


286

むかしむかし、多くの月前に、VS6が存在し、人気がありました。しかし、多くのC ++標準に準拠できませんでした。これは、規格が正式にリリースされる直前(同じ年)にリリースされた当時は妥当でした。しかし、私が知る限り、それは規格の草案に忠実でした。

ドラフトと公式標準の間で変更された標準の1つは、最初のセクションで作成されたforループ変数の寿命です。コンパイルに失敗する次のコードにつながる

{
    for (int i=0; i<1; ++i){}
    for (int i=0; i<2; ++i){}
}

理由はi2番目のforループによって再定義されました。

他のコンパイラにもこのバグがありましたが、VS6を強調表示します。これは、VS6が標準のリリース後、長年にわたってVisual Studioの唯一のバージョンであったためですが、この特定の問題の更新はリリースしていません。より重要な影響があったことを意味します。

これに対する解決策は、示したようにforループ全体を独自のスコープに強制することです。


49
VS6を見つける必要はありません、その@bolovを参照してくださいVS2015で「いいえ」に設定し、「Forループスコープの力適合性」、および;-)楽しむん
アラン・

5
@alain "オプション 'Zc:forScope-'は非推奨になり、将来のリリースで削除される予定です"と問題なくコンパイルされます...悲しい
bolov

7
バージョン2.7より前のGCCもこの動作を示しました。docs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy

5
@Damon VS6が最初にリリースされたときではありません。ただし、標準が変更された場合、標準に準拠したアップデートはリリースされませんでした。VS6は、規格が変更されてから数年間人気がありました。
UKMonkey

7
これを古いMicrosoftコンパイラの罪のせいにするのは偽りです。この動作は実際にはドラフトC ++標準の機能であり、(Microsoftコンパイラーだけでなく)多くのコンパイラーがこれを行いました。メモリから、変数はループに対してローカルになるように1995年頃にドラフトで変更されました-最初のC ++標準が承認される約3年前。したがって、1996年より前のほとんどのC ++コンパイラはこの方法で機能しました。
Peter

15

{そして、}スコープを作成し、あなたがスコープ内にいくつかの変数を定義する場合は、外部からそれらにアクセスすることはできません。しかし、forすでにそのスコープを作成しています。そう

{for(int i = 0; i < count; ++i){}} 

と同じです

for(int i = 0; i < count; ++i){}

しかし、あなたがそれらの間に何かを定義すると、違いがあります

{int a = 0; for(int i = 0; i < count; ++i){}}

この例でaは、スコープ外からはアクセスできません。


2

あなたの特定の例では、それらの理由はありません。

変数のスコープを作成したい場合があります。

float average;
// ...

{
int sum = 0;
for (int i = 0; i < count; ++i)
{
   sum += v[i];
}
average = (float)sum / count;
}

// use average
// sum not in scope here

しかし、これはアンチパターンだと思います。通常、これを行う必要がある場合は、おそらくfor独自の機能でなければなりません。


それが独自の機能である必要があると考えている場合は大丈夫です(少なくともオーバーヘッドが増えるだけのことは何度も考えられますが、そこには行きません)。あなたのための架空の質問:必要な場合はどうでしょうかスイッチケースに特定のローカルスコープ?確かに、追加のスコープ(もちろん、関数もそうです)を追加する必要があります(例では、私はまったく別の関数を使用するのは悪い考えではないことに注意してください)が不要な場合もあります。他の方法があります。
プリフタン2018

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