57885


次のようなコードを実行したとき、printf()の引数リストで生成したstd::stringのデストラクタが呼び出されるのはprintfの実行が終わってから、ということでよかったでしょうか？

適当なclassを実装して試せばそのコンパイラでの動作は確かめられますが、規格で定義されているのかが気になりました。

[code]

    int main(int argc, char *argv[])
    {
        printf("%s %s\n", std::string("A").c_str(),  std::string("B").c_str());
    
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2019-09-06T01:07:47.500
57882
2019-09-06T06:03:53.023
17238
question
c++
C++で関数の引数リスト内で一時オブジェクトを生成した時のデストラクタが呼び出されるタイミング


引用はいいんよう、という話だったのでオイラの手元の言語規格書より一部引用。

この辺 `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) を除き、第二の式 または 第三の式を評価する前に発生する。


CC BY-SA 4.0
2019-09-06T01:44:15.293
57885
2019-09-06T06:03:53.023
2019-09-06T06:03:53.023
8589
8589
57882
answer