13

かなり基本的な C++ の質問があります。いくつかの入力パラメーターを受け取り、std::stringそれらのパラメーターから次のようなを作成する関数を考えてみましょう。

std::string constructString( int some_parameter ) {
    
    std::stringstream ss;
    
    // Construct a string (arbitrarily complex)
    ss << "Some parameter is " << some_parameter << " right now";

    return ss.str();    //Am I not returning a temporary object here?
}

stringstream関数が戻るときにオブジェクトがスコープ外になることは理解していますが、それによって構築された文字列も無効になりませんか?

const char *戻り値の型を に変更して返すとどうなりss.str().c_str()ますか?

上記のようなコードは機能しているように見えますが、それは単に「一時」オブジェクトを含むメモリが使用時に別のものでまだ上書きされていないためではないでしょうか?

私は認めざるを得ませんが、一般的にそのような状況ではかなり混乱しています。誰かがこの「一時的なオブジェクト」全体を説明してくれれば (または、正しい方向に向けてくれれば) ありがたいです。

4

3 に答える 3

19

一時オブジェクトを返していますが、値で返すため、コピーが作成されます。一時オブジェクトへのポインターまたは参照を返す場合、それは間違いです。

戻り値の型をに変更して返すconst char *と、返されたss.str().c_str()一時的なバッファへのポインタがstd::string返されss.str()、それは悪いことです。

于 2012-10-18T10:18:46.873 に答える
5

ご覧のとおり、 Stringstream::str()はオブジェクトを返しstd::stringます。参照なしで返すstd::stringということは、RVO(NRVO) 最適化なしでコピー コンストラクターが呼び出して有効なstd::stringオブジェクトを作成することを意味します。最適化によりstd::string、コピー コンストラクターなしで移動されます。ただし、std::string&関数が返された後にこのオブジェクトが破棄されるため、関数が返されるとクラッシュします。const char *このポインターを破棄した後、不良メモリを指し、これは危険な状況になるため、同じ効果があります。

于 2012-10-18T10:21:07.883 に答える
1

C++T val = some_function()から値を返す場合、指定されたコピー コンストラクターまたは組み込み演算子を使用して、返された値の値をコピーします。つまり、orを返せばまったく問題ありませんが、関数の最後に解放されるメモリへのポインタを返すと、おっと!! ポインタは無効なメモリを指します。たとえば、次のように考えてください。some_functionvalintstd::string

const char* some_function() {
    std::string res( ... );
    //...
    return res.c_str();
}

関数が戻るとすぐに解放されるデータへのポインターを返しているため(res破棄され、内部データが解放されるため)、アドレスを取得しますが、そのアドレスはおそらく期待するものを指していません!

于 2012-10-18T10:26:21.193 に答える