43

関数、クラス、if、while、switch、try-catchに必要なときに使用する以外の意味です。

このSOの質問を見るまで、このようにできるとは知りませんでした。

上記のリンクで、Eliは、「通常は折りたたまれる関数、クラス、ループなどに分類されない論理セクションでコードを折りたたむために使用します」と述べています。

上記以外にどのような用途がありますか?

中括弧を使用して変数のスコープを制限し、必要な場合にのみスコープを拡張することをお勧めします(「アクセスの必要性」に基づいて作業します)。それとも実際にはばかげていますか?

異なるスコープで同じ変数名を同じ大きなスコープで使用できるようにするために、スコープを使用するのはどうですか?または、同じ変数を再利用して(同じ変数名を使用する場合)、割り当て解除と割り当てを節約することをお勧めします(一部のコンパイラーはこれを最適化できると思いますか?)。それとも、異なる変数名を一緒に使用する方が良いですか?

4

13 に答える 13

52

特定の時間に解放したいリソースを使用している場合は、次のようにします。

void myfunction()
{
  {
  // Open serial port
     SerialPort port("COM1", 9600);
     port.doTransfer(data);
  } // Serial port gets closed here.

  for(int i = 0; i < data.size(); i++)
     doProcessData(data[i]);
  etc...
}
于 2008-10-30T01:35:23.267 に答える
39

いくつかの理由から、その目的で中括弧を使用することはありません。

  1. 特定の関数が十分に大きいため、さまざまなスコーピングトリックを実行する必要がある場合は、関数をより小さなサブ関数に分割することをお勧めします。

  2. 変数名を再利用するためにスコープに中括弧を導入すると、コードの混乱と問題が発生するだけです。

ちょうど私の2セントですが、他のベストプラクティスの資料でこれらの種類のものをたくさん見ました。

于 2008-10-30T01:34:55.640 に答える
17

C ++

必要に応じて、変数名を再利用するために、追加のブレースレベルのスコープを導入する必要がある場合があります。

switch (x) {
    case 0:
        int i = 0;
        foo(i);
        break;
    case 1:
        int i = 1;
        bar(i);
        break;
}

上記のコードはコンパイルされません。あなたはそれを作る必要があります:

switch (x) {
    case 0:
        {
            int i = 0;
            foo(i);
        }
        break;
    case 1:
        {
            int i = 1;
            bar(i);
        }
        break;
}
于 2008-10-30T01:40:20.120 に答える
16

私が定期的に使用するスコープの最も一般的な「非標準」の使用法は、スコープ付きミューテックスを利用することです。

void MyClass::Somefun()
{
    //do some stuff
    {
        // example imlementation that has a mutex passed into a lock object:
        scopedMutex lockObject(m_mutex); 

        // protected code here

    } // mutex is unlocked here
    // more code here
}

これには多くの利点がありますが、最も重要なのは、保護されたコードで例外がスローされた場合でも、ロックが常にクリーンアップされることです。

于 2008-10-30T13:25:24.410 に答える
14

他の人が言っているように、最も一般的な使用法は、デストラクタが必要なときに実行されるようにすることです。また、プラットフォーム固有のコードをもう少し明確にするのにも便利です。

#if defined( UNIX )
    if( some unix-specific condition )
#endif
    {
        // This code should always run on Windows but 
        // only if the above condition holds on unix
    }

Windows用にビルドされたコードは、ifを認識せず、中括弧のみを認識します。これは、次のよりもはるかに明確です。

#if defined( UNIX )
    if( some unix-specific condition ) {
#endif
        // This code should always run on Windows but 
        // only if the above condition holds on unix
#if defined( UNIX )
    }
#endif
于 2008-10-30T13:34:25.297 に答える
6

コードジェネレーターにとっては恩恵となる可能性があります。Embedded SQL(ESQL)コンパイラーがあるとします。SQLステートメントをローカル変数を必要とするコードのブロックに変換したい場合があります。ブロックを使用することで、すべての変数を別々の名前で作成するのではなく、固定変数名を何度も再利用できます。確かに、それはそれほど難しいことではありませんが、必要以上に難しいです。

于 2008-10-30T01:36:04.497 に答える
6

他の人が言ったように、これは C++ ではかなり一般的です。これは、強力な RAII (リソースの取得は初期化です) イディオム/パターンによるものです。

ヒープベースのオブジェクトと GC は RAII を無効にするため、Java プログラマー (そしておそらく C# も私にはわかりません) にとって、これはなじみのない概念です。オブジェクトをスタックに置くことができることは、Java に対する C++ の最大の利点であり、適切に作成された C++ コードは、適切に作成された Java コードよりもはるかにクリーンになります。

于 2008-10-30T01:56:53.690 に答える
5

私は、RAIIを使用して何かを解放する必要がある場合にのみ使用します。それでも、できるだけ早く解放する必要がある場合(たとえば、ロックを解放する場合)にのみ使用します。

于 2008-10-30T01:36:54.887 に答える
3

Java でのプログラミング メソッド内でスコープを制限したいと思ったことはよくありますが、ラベルを使用することは思い浮かびませんでした。ブレークのターゲットとしてラベルを使用するときにラベルを大文字にするので、あなたが提案したように大文字と小文字が混在するラベル付きブロックを使用することは、これらの機会に私が望んでいたことです。

多くの場合、コード ブロックは短すぎて小さなメソッドに分割できません。多くの場合、コードはフレームワーク メソッド (startup() や shutdown() など) 内にあり、実際にはコードを 1 つのメソッドにまとめる方が適切です。

個人的には、単純なフローティング/ダングル ブレースが嫌いです (ただし、これは、厳密なバナー スタイルのインデント ショップであるためです)。コメント マーカーも嫌いです。

// yuk!
some code
{
scoped code
}
more code

// also yuk!
some code
/* do xyz */ {
    scoped code
    }
some more code

// this I like
some code
DoXyz: {
    scoped code
    }
some more code

「if(true) {」を使用することを検討したのは、Java の仕様でこれらがコンパイル時に最適化されると具体的に述べられているためです (if(false) の内容全体と同様に - これはデバッグ機能です)。私はそれを試してみました。

ですから、あなたのアイデアは良いものだと思います。まったくばかげているわけではありません。これをやりたいのは私だけだといつも思っていました。

于 2008-11-01T20:21:35.267 に答える
1

はい、RAII のためにこの手法を使用しています。この手法は、変数を互いに近づけるため、プレーンCでも使用します。もちろん、もっと機能を分解することも考えるべきです。

私が行うことの 1 つは、スタイル的におそらく物議を醸すことですが、宣言の行に開始中括弧を配置するか、その上にコメントを配置することです。縦方向の無駄なスペースを減らしたい。これは、Google C++ スタイル ガイドの推奨事項に基づいています。.

/// c++ code
/// references to boost::test
BOOST_TEST_CASE( curly_brace )
{
  // init
  MyClass instance_to_test( "initial", TestCase::STUFF ); {
    instance_to_test.permutate(42u);
    instance_to_test.rotate_left_face();
    instance_to_test.top_gun();
  }
  { // test check
    const uint8_t kEXP_FAP_BOOST = 240u;
    BOOST_CHECK_EQUAL( instance_to_test.get_fap_boost(), kEXP_FAP_BOOST);
  }
}
于 2008-11-01T04:38:06.170 に答える
0

その場所はありますが、同じ関数または他の(字句ではなく論理的な)スコープ内で$ fooをここで1つの変数にし、別の変数にすることは良い考えではないと思います。コンパイラはそれを完全に理解しているかもしれませんが、コードを読み込もうとする人間の生活を困難にする可能性が高すぎるようです。

于 2008-10-30T02:38:17.477 に答える
0

私はアガルツケに同意します。読みやすくするために、より大きな論理コード ブロックをセグメント化する必要があると思われる場合は、ビジーで雑然としたメンバーをクリーンアップするためのリファクタリングを検討する必要があります。

于 2008-10-30T01:51:37.680 に答える
0

私が働いている会社には、ローカル変数宣言を関数の先頭近くに保持するという静的分析ポリシーがあります。多くの場合、使用法は関数の最初の行の後に何行もあるため、画面上で宣言と最初の参照を同時に見ることができません。ポリシーを「回避」するために私が行うことは、宣言を参照の近くに保持することですが、中括弧を使用して追加のスコープを提供します。ただし、インデントが増え、コードが醜くなると主張する人もいます。

于 2010-09-03T17:27:42.290 に答える