2012-09-07 3 views
17

可能性の重複:
Lifetime of temporaries一時的なパラメータ値はいつスコープから外れますか?

int LegacyFunction(const char *s) { 
    // do something with s, like print it to standard output 
    // this function does NOT retain any pointer to s after it returns. 
    return strlen(s); 
} 

std::string ModernFunction() { 
    // do something that returns a string 
    return "Hello"; 
} 

LegacyFunction(ModernFunction().c_str()); 

上記の例では、簡単に文字列の代わりにスマートポインタを使用するように書き換えることができ、私はこれらの状況の両方に何度も遭遇しました。とにかく、上記の例では、ModernFunctionにSTL文字列を作成し、それを返し、文字列オブジェクトの内部のCスタイルの文字列へのポインタを取得し、そのポインタをレガシー関数に渡します。

  1. ModernFunctionが返された後に存在する一時的な文字列オブジェクトがあります。それはいつスコープから外れますか?
  2. コンパイラがc_str()を呼び出し、この一時的な文字列オブジェクトを破棄してから、手掛かりのあるポインタをLegacyFunctionに渡すことは可能ですか? (文字列オブジェクトがc_str()が返す値が指すメモリを管理していることを覚えておいてください)
  3. 上記のコードが安全でない場合、それはなぜ安全ではないのですか?それは関数呼び出しを行うときに一時変数を追加するよりですか?それが安全ならば、なぜですか?コピーの
+0

私はちょうどこれをコンパイルし、それは働いた。 ForEveRの答えによれば、それもうまくいくはずです。 –

+2

@ H2CO3、 "それは働いた"何も証明することはありません - 時々あなたは幸運を得る。あなたがそれを試して、それが*働かなかったら、それは違うでしょう。 –

+0

@ MarkRansomは、「ForEveRの答えによれば、それもうまくいくはずだ」と気付いた? (明確にするために:私はそれを知っています) –

答えて

14
LegacyFunction(ModernFunction().c_str()); 

破壊はfull expressionの評価後(即ちLegacyFunctionからの復帰後に)であろう。

n3337 12.2/3

一時オブジェクトは、(字句)は、それらが作成された点を含んでいることをフル式(1.9)評価の最後のステップ ように破壊されます。

n3337 1.9/10

フル発現は、他の式の部分式ではない式です。関数の暗黙の呼び出しを生成するために言語構造 が定義されている場合、言語構造の使用はこの定義の目的で 式と見なされます。寿命の終わりに の一時オブジェクト以外のオブジェクトが生成されたデストラクタへの呼び出しは、暗黙の完全な式です。 の結果に適用される変換は、式が と表示される言語構成の要件を満たすためにも、完全表現の一部とみなされます。 [例:

struct S { 
S(int i): I(i) { } 
int& v() { return I; } 
private: 
int I; 
}; 
S s1(1); // full-expression is call of S::S(int) 
S s2 = 2; // full-expression is call of S::S(int) 
void f() { 
if (S(3).v()) // full-expression includes lvalue-to-rvalue and 
// int to bool conversions, performed before 
// temporary is deleted at end of full-expression 
{ } 
} 

9

ModernFunctionが戻った後に存在する一時的な文字列オブジェクトがあります。それはいつスコープから外れますか?

厳密に言えば、スコープに決してありません。スコープは、オブジェクトではなく名前のプロパティです。自動変数は、スコープの間に非常に近い関連性を持ちます。寿命はです。自動変数ではないオブジェクトは異なります。

テンポラリオブジェクトは、それらが現れる完全表現の最後に破棄されますが、ここでは関係のないいくつかの例外があります。とにかく特別な場合の寿命を一時的に延ばすが、それを減らさない。コンパイラは除く(、c_str()を呼び出し、この一時的な文字列オブジェクトを破壊した後、完全な式がLegacyFunction(ModernFunction().c_str())あるので、

いいえLegacyFunctionするダングリングポインタを渡すため

は可能ですセミコロン:そのpedantryを感じる)ので、戻り値 ModernFunctionの一時的なものは、 LegacyFunctionが返されるまで破壊されません。

安全なのはなぜですか?

一時的なライフタイムが十分に長いためです。

一般にc_strでは、2つのことについて心配する必要があります。最初に、文字列が破棄された場合に返されるポインタは無効になります(これはあなたが求めているものです)。第2に、文字列が変更された場合に返されるポインタは無効になります。あなたはそれについて心配していませんが、それは問題ありません。なぜなら、文字列を変更するものもないからです。

関連する問題