• ベストアンサー

ostringstreamではまりました

const char*を受け付ける関数に、文字列を組み立てて渡すために、 以下のようにしました。 しかし、結果何も出力されません。 どこがまずいのでしょうか? std::ostringstream str_stream; str_stream << "aiueo" << 33; const char* c_str = str_stream.str().c_str(); std::cout << c_str << std::endl;

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

> std::string moji = str_stream.str(); > const char* c_str = moji.c_str(); この場合、moji が、最後まで生き残っていますから、moji.c_str() は有効なC文字列の先頭をポイントし続けます。 > const char* c_str = str_stream.str().c_str(); こちらの場合は、str_stream にある実体から、一度、std::string が生成されて、この行を抜けると破棄される。 その破棄されたオブジェクトが提供していたポインタを見ているので、それは保証されないというところです。 std::string は、C文字列を内部的に持っていて、それをもとにデータを加工しているような実装が普通には考えられます。 strstream も、内部的に、string を持っていて、それをもとにデータを加工しているような実装が普通には考えられます。 その場合、「破棄された」といっても、C文字列が入っているメモリそのもには、(再利用されるまで)そのまま残っているケースがあります。 との場合には、たまたま、「破棄された」C文字列のポインタが、もともと、文字列が入っていた領域をポイントしていて、そこには、まだ、以前の文字列が残っているという可能性もあります。 この場合に、たまたま動いているように見えるということですね。 上記のような実装は、必須ではないですし、もしかしたら、破棄されるときにデータ領域をちゃんと消していく実装もあるかもしれません。 その場合は、動いていないように見えるということになるのでしょう。

rotofrot
質問者

お礼

ありがとうございます。 からくりがよく理解できました。

その他の回答 (4)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.4

MSDN で c_str() の戻り値を見ると ------- 引用 ------ The pointer value is not valid after calling a non-const function, including the destructor, in the basic_string class on the object. ------------------- と書いてあるから、str_stream.str() で作成された一時オブジェクトが破棄された後、c_str の値は保証されないようですね。 単に string("aiueo").c_str() としてもやはり NG みたい。これはハマリそう。

rotofrot
質問者

お礼

引用までしていただいてありがとうございます。 理解できました。

  • HowOver
  • ベストアンサー率30% (17/56)
回答No.3

あーなるほどーそうでしたか 私一般人なのでただ見てるだけのつもりだったんですけど 全角に気づいたので突っ込んでみただけなのでなんともですけど、 こちらでは全角取り除けば"aiueo33"って出ますよ? 素人なので不正確になってしまいますけど私のコンパイラは gcc ver3.2 か 3.4.2 みたいですけど。 そちらは何をお使いで?

rotofrot
質問者

補足

ありがとうございます。 失礼しました。 こちらの環境はVC++2008 Express Editionです。 cygwinでgcc 3.4.4で同じコードをコンパイルして動かすと 問題なく動きました。 VCのバグか何かなのでしょうか… それともgccではたまたま動いているだけなのでしょうか。

回答No.2

> const char* c_str = str_stream.str().c_str(); str_stream.str() で一時的に作られた string の寿命が 極めて短く、c_str() が評価された直後にデストラクト されているのでしょうね。

rotofrot
質問者

補足

回答ありがとうございます。 なるほど、つまり、 const char* c_str = str_stream.str().c_str(); の行が終わった時点でstr()によって取得したstringオブジェクトは 破棄されてしまうというわけですか。 疑問があるのですが、これはC++の標準の動きなのでしょうか? というのも、同じコードcygwinでg++でコンパイルしたら問題なく 動作しました。 書き忘れていたのですが、質問時のコードはVC++2008 Expressでコンパイルしました。 VC++9.0のバグ、ということはないでしょうか? VC++9.0とg++ではどちらが正しい動きをしているのでしょうか?

  • HowOver
  • ベストアンサー率30% (17/56)
回答No.1

"aiueo" << 33; "と<< のあいだに 全角スペースはいっとりまっせ~ これははまるは そのまま貼り付けなかったら解決しませんでしたね

rotofrot
質問者

補足

すみません。全角スペースはタイプミスです。 手元のソースでは普通のスペースになっています。 コンパイルは通ることを確認しています。 失礼しました。 全角スペース問題ではないようです。 よくわからないのは、以下のようにするとうまく動くことです。 std::string moji = str_stream.str(); const char* c_str = moji.c_str(); どうして、 const char* c_str = str_stream.str().c_str(); と一行でまとめて書くとうまくいかないのでしょうか。

関連するQ&A