質問: 次のようなコードを実行したとき、printf()の引数リストで生成したstd::stringのデストラクタが呼び出されるのはprintfの実行が終わってから、ということでよかったでしょうか? 適当なclassを実装して試せばそのコンパイラでの動作は確かめられますが、規格で定義されているのかが気になりました。 ``` int main(int argc, char *argv[]) { printf("%s %s\n", std::string("A").c_str(), std::string("B").c_str()); return 0; } ```
回答: 引用はいいんよう、という話だったのでオイラの手元の言語規格書より一部引用。 この辺 `move semantics` の絡みがあって規格書の改版で変わっているはずの個所ですが、古くてよければ `ISO/IEC 14882:1998` (`C++98`) および `JIS X3014:2003` (`C++03`) ではほとんど全く同じで 12.2 Temporary objects の 3 一時オブジェクトの解体は、それを生成した時点を(字句的に)含む完結式 (1.9) の評価の最終段階で行う。 1.9 Program execution の 12 他の式の部分式となっていない式を完結式 (full-expression) と呼ぶ。 完結式 (full-expession) がわかりにくいですが、要するに「式文」の全体は完結式っす。提示例では `printf()` を呼んでいる式文のセミコロン位置が完結式終了位置。つまり `printf()` の実行が完了し、呼び出し元に復帰した後で一時オブジェクトが解体されます。提示コードは規格厳密一致ですね。 関数呼び出しの引数の評価順は未規定なので、提示例では `"A"` と `"B"` の `std::string` のどっちが先に構築されるかはコンパイラによって違ってよくて、同一コンパイラでもコンパイルオプションによって違ってよくて、コンパイラベンダによって文書化される義務がありません。ただし、構築の逆順に解体されることは決まっています。 12.2 の 3 が適用されない場合は 12.2 の 4 および 5 ですが提示例に該当しないので省略(気になるのでしたら規格書お買い上げください) 追記:完結式の途中に副作用完了点がある場合でも (12.2-3) で述べてある解体は例外で、完結式(式文と読み替えてよし)の終了の時点まで遅延されます。例えば `?:` のとこから引用(他の演算子のところにも明記されています) 5.16 二択条件演算子 の 1 第一の式についてのすべての副作用は、一時変数の解体 (12.2) を除き、第二の式 または 第三の式を評価する前に発生する。