goto では、デストラクタは呼ばれる
僕は、goto
が嫌いだ。まあ、好きな人なんていないとは思うが。一度でも“今は亡き前任者の goto
”に泣かされたことがあれば、全ての goto
文は「goto HELL;
」にしか見えなくなるはずだ。“goto
文の全てが悪いわけではない”、“多重ループからの脱出には goto
が分かりやすい”、といった主張には概ね賛成だが、それでも、「いい goto
と悪い goto
を見分けるぐらいなら、一律禁止の方が全体的作業効率はいい」というのが正直な感想だ。弊害が多すぎる上に無ければ無いで大して困らない((大抵の goto
は、return
でうまく書き直せる。その結果として関数がほどよく分割されて全体的な読みやすさが向上することもよくある。))もの、それが goto
。
このように goto
を毛嫌いしている僕としては、goto
のない正しい未来を正当化する理由を常に探しているわけで、longjmp()
はスタックを正しく巻き戻せないので C++ 的には使えない、ということを知った刹那、「じゃあ、goto
もダメなんじゃないの((longjmp()
関数は、“関数間での goto
”と説明されることもよくある。個人的には goto
というよりかは break
だと思うが、「break
など goto
に過ぎぬわっ!!」と言われる方もいらっしゃる。))?」という邪な考えが頭をよぎった。
ところが、残念なことに、C++ の goto
は、それによってスコープから外れたオブジェクトのデストラクタを正しく呼び出してしまう:
- C++ 標準*1 ― 6.6
-
Jump statements unconditionally transfer control.
jump-statement: break ; continue ; return expressionopt ; goto identifier ;
On exit from a scope (however accomplished), destructors (12.4) are called for all constructed objects with automatic storage duration (3.7.2) (named objects or temporaries) that are declared in that scope, in the reverse order of their declaration.
goto
を葬り去るのには失敗したが、よく考えたら、最近は goto
を書こうという人をそもそも見かけない。
*1:ISO/IEC 14882:2003(E)。