2

以下の動作について、標準に説明はありますか?

次のコード:

#include <sstream>
#include <iostream>

using namespace std;

int main()
{
    ostringstream os1;
    ostringstream os2;

    os1 << 1 << " " << 2;
    os2 << 1 << " " << 2 << " " << 3;

    const char *p = os1.str().c_str();

    cout << os2.str() << endl;
    cout << p << endl;

    return 0;
}

出力を表示します。

1 2 3
1 2 3

ただし、次のように表示されると思います。

1 2 3
1 2 

os1 オブジェクトが何らかの形で os2 の影響を受けているように見えます。os2.str() 呼び出しを削除すると、サンプルは正しく動作します。

Solaris Studio 12.2 と G++ 4.8.1 の例を試してみましたが、どちらも同じように動作します。

ご協力いただきありがとうございます!

4

3 に答える 3

4
const char *p = os1.str().c_str();

これが問題です、上記の行にあります。

os1.str()内部文字列バッファをコピーして、一時的な文字列オブジェクトを返します。そして.c_str()、完全な式の最後で破棄される一時オブジェクトを取得しています。結果は、pを使用して印刷するときに、破棄されたオブジェクトを指しますstd::cout

つまり、プログラムは未定義の動作 (UB) を呼び出します。

これを試して:

auto s = os1.str();  
const char *p = s.c_str(); //s is not a temporary object anymore!

これで正しい出力が得られます(これがあなたのコードです— 幸いなことに、coliru でさえ、あなたのマシンで観察したのと同じ出力が得られます。コードが UB を呼び出すという理由だけで、この出力は保証されないことに注意してください)。

于 2013-10-20T13:24:53.167 に答える
2

問題は、によって返されたポインターを保持することに関係していると思いますc_str()

ostringstream::str()一時的な文字列オブジェクトを返し、その内部char配列へのポインターを保存しています。ただし、その行が実行されると、返された文字列オブジェクトは削除されます。したがって、ポインタは無効になります。

何らかの理由で c_str ポインターを保持したい場合は、文字列のコピーも保持する必要があります。

string s = os1.str();
const char *p = s.c_str();

cout << os2.str() << endl;
cout << p << endl;
于 2013-10-20T13:29:34.610 に答える
0

この質問に対する答えは次のとおりです: stringstream、string、および char* 変換の混乱

stringstream.str() は、完全な式の最後で破棄される一時的な文字列オブジェクトを返します。その (stringstream.str().c_str()) から C 文字列へのポインターを取得すると、ステートメントが終了する場所で削除される文字列を指します。

于 2013-10-20T13:30:25.483 に答える