私が次のように書いた場合、void func(const char *str);
参照は有効かどうか疑問に思います:str
auto str = string("hello").c_str();
func(str);
以下のコードとどう違うのですか?
func(string("hello").c_str())
どちらの場合も、string
オブジェクトは一時的なものであり、ステートメントの最後で破棄されます。
最初のケースでstr
は、ぶら下がってしまいます-一時的に管理されてstring
いたが、現在は破棄されているメモリを指しています。それを使って何かをすることはエラーであり、未定義の振る舞いを与えます。
string
2番目のケースでは、関数が戻るまで一時は破棄されません。したがって、関数が後で他の何かを使用するためのポインタを保持しない限り、これは問題ありません。
string
違いは、最初のステートメントが最初のステートメントの最後で破棄される一時オブジェクトを作成するためstr
、ダングリングポインターになることです。func
2つ目も一時オブジェクトを作成しますが、一時オブジェクトは呼び出しが戻るまで破棄されないため、呼び出し全体に存在しfunc
ます。
C ++11標準の12.2/3項から:
[...]一時オブジェクトは、それらが作成されたポイントを(字句的に)含む完全式(1.9)を評価する最後のステップとして破棄されます。これは、その評価が例外のスローで終了した場合でも当てはまります。[...]
これは、toの呼び出しを含む式内に作成された一時的なものが、func()
関数呼び出しが戻るまで存続することを意味します。
一方、最初のコードスニペットの一時的な有効期間は、func()
呼び出される前に終了し、str
ぶら下がっています。これにより、未定義の動作が発生します。