「dowhile」と「gotoout」は、これらの領域で異なります。
1.ローカル変数の初期化
void foo(bool t = false)
{
if (t)
{
goto DONE;
}
int a = 10; // error : Goto bypass local variable's initialization
cout << "a=" << a << "\n";
DONE:
}
do ... while(0)ブロックでインプレースローカル変数を初期化するのは問題ありません。
void bar(bool t = false)
{
do{
if (t)
{
break;
}
int a = 10; // fine
cout << "a=" << a << "\n";
} while (0);
}
マクロの2つの違い。「dowhile」は少し良いです。マクロの「gotoDONE」はそうではありません。終了コードがより複雑な場合は、次のようになります。
err = some_func(...);
if (err)
{
register_err(err, __LINE__, __FUNC__);
#if defined (_DEBUG)
do_some_debug(err)
#endif
break;
}
そして、このコードを何度も書くと、おそらくそれらをマクロに入れるでしょう。
#define QUIT_IF(err) \
if (err) \
{ \
register_err(err, __LINE__, __FUNC__); \
DO_SOME_DEBUG(err) \
break; // awful to put break in macro, but even worse to put "goto DONE" in macro. \
}
そして、コードは次のようになります。
do
{
initial();
do
{
err = do_step1();
QUIT_IF(err);
err = do_step2();
QUIT_IF(err);
err = do_step3();
QUIT_IF(err);
....
} while (0);
if (err) { // harder for "goto DONE" to get here while still using macro.
err = do_something_else();
}
QUIT_IF(err);
.....
} while (0);
3.do ... while(0)は、同じマクロでさまざまなレベルの終了を処理します。コードは上に示されています。goto ...はマクロには当てはまりません。これは、レベルごとに異なるラベルが必要になるためです。
そういえば、どちらも好きではありません。例外メソッドを使用したいと思います。例外が許可されていない場合は、「do ... while(0)」を使用します。ブロック全体がインデントされているため、「gotoDONE」スタイルよりも実際に読みやすくなっています。