追加のスコープに中括弧を使用しますか? [閉まっている]
-
05-07-2019 - |
質問
関数、クラス、if、while、switch、try-catchに必要なときに使用する以外のことを意味します。
のように実行できることを知りませんでした私はこのSO質問を見るまで。
上記のリンクで、イーライは、「通常は折りたたまれる関数、クラス、ループなどに分類されない論理セクションにコードを折りたたむために使用する」と述べました
言及した用途以外に他にどのような用途がありますか?
中括弧を使用して変数のスコープを制限し、必要な場合にのみスコープを拡張することをお勧めします(「アクセスが必要」ベースで作業する)?それとも実際に愚かですか?
同じ変数名を異なるスコープで同じスコープで使用できるように、スコープを使用するのはどうですか?または、同じ変数を再利用し(同じ変数名を使用したい場合)、割り当て解除と割り当てを節約することをお勧めします(一部のコンパイラはこれで最適化できると思いますか?)それとも、異なる変数名をすべて使用する方が良いですか?
解決
特定の時間に解放したいリソースを使用している場合、例:
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...
}
他のヒント
いくつかの理由で、その目的で中括弧を使用しません。
-
特定の関数が十分に大きく、さまざまなスコープトリックを実行する必要がある場合は、関数を小さなサブ関数に分割する可能性があります。
-
変数名を再利用するためにスコープの括弧を導入しても、コードの混乱とトラブルにつながるだけです。
たったの2セントですが、他のベストプラクティスの資料でこれらのタイプの多くを見てきました。
最も一般的な「非標準」私が定期的に使用するスコープの使用は、スコープ付きミューテックスを利用することです。
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
}
これには多くの利点がありますが、最も重要なことは、保護されたコードで例外がスローされた場合でも、ロックが常にクリーンアップされることです。
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;
}
他の人が言っているように、最も一般的な使用法は、デストラクタを必要なときに実行することです。プラットフォーム固有のコードを少し明確にするのにも便利です:
#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
コードジェネレーターの恩恵を受けることができます。 Embedded SQL(ESQL)コンパイラーがあるとします。 SQLステートメントをローカル変数を必要とするコードブロックに変換したい場合があります。ブロックを使用することにより、すべての変数を別々の名前で作成するのではなく、固定変数名を繰り返し再利用できます。確かに、それほど難しくはありませんが、必要以上に難しいです。
他の人が言ったように、これは強力なRAII(リソースの取得は初期化)のイディオム/パターンのため、C ++ではかなり一般的です。
Javaプログラマー(および多分C#かもしれませんが)には、ヒープベースのオブジェクトとGCがRAIIを強制終了するため、これは外国の概念になります。私見、スタックにオブジェクトを配置できることは、Javaに対するC ++の最大の単一の利点であり、適切に記述されたC ++コードを、適切に記述されたJavaコードよりもはるかにクリーンにします。
RAIIを使用して何かをリリースする必要がある場合にのみ使用します。それでも、できるだけ早くリリースする必要がある場合(たとえば、ロックを解除する場合)にのみ使用します。
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
&quot; if(true){&quot; Javaの仕様では、これらはコンパイル時に最適化されると明確に述べられているため(if(false)のコンテンツ全体と同じように-これはデバッグ機能です)、私はいくつかの場所で試したことを嫌っていました。
だから、あなたの考えはいい考えだと思う。これをやりたかったのは自分だけだといつも思っていました。
はい、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);
}
}
agartzkeに同意します。読みやすくするために、より大きな論理コードブロックをセグメント化する必要があると思う場合は、リファクタリングを検討して、忙しく混雑しているメンバーをクリーンアップする必要があります。
その場所はありますが、同じ関数内で$ fooを1つの変数 here と異なる変数 there にできるようにすることは考えていませんまたは、他の(レキシカルではなく論理的な)スコープが良い考えです。コンパイラーはそれを完全に理解しているかもしれませんが、人間がコードを読もうとするのを困難にする可能性が高すぎるようです。
私が働いている会社には、関数の先頭近くにローカル変数宣言を保持するための静的分析ポリシーがあります。多くの場合、使用法は関数の最初の行の後の多くの行なので、画面上で宣言と最初の参照を同時に見ることができません。ポリシーを「回避」するために私がすることは、宣言を参照の近くに保ちながら、中括弧を使用して追加のスコープを提供することです。ただし、インデントが増加し、コードの見栄えが悪くなると主張する人もいるかもしれません。