質問 |
||
| 質問者:rotofrot | 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; |
|
質問投稿日時:08/04/08 05:33 質問番号:3931440 |
||
回答良回答20pt |
|
| 回答者:AsanoNagi | > 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文字列のポインタが、もともと、文字列が入っていた領域をポイントしていて、そこには、まだ、以前の文字列が残っているという可能性もあります。 この場合に、たまたま動いているように見えるということですね。 上記のような実装は、必須ではないですし、もしかしたら、破棄されるときにデータ領域をちゃんと消していく実装もあるかもしれません。 その場合は、動いていないように見えるということになるのでしょう。 |
|---|---|
| 種類:回答 どんな人:一般人 自信:参考意見 |
|
| |
回答日時:08/04/08 09:11 回答番号:No.5 |
|
| この回答へのお礼 | ありがとうございます。 からくりがよく理解できました。 |
回答良回答10pt |
|
| 回答者:koko_u_ | 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 みたい。これはハマリそう。 |
|---|---|
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| |
回答日時:08/04/08 08:53 回答番号:No.4 |
|
| この回答へのお礼 | 引用までしていただいてありがとうございます。 理解できました。 |
回答 |
|
| 回答者:HowOver | あーなるほどーそうでしたか 私一般人なのでただ見てるだけのつもりだったんですけど 全角に気づいたので突っ込んでみただけなのでなんともですけど、 こちらでは全角取り除けば"aiueo33"って出ますよ? 素人なので不正確になってしまいますけど私のコンパイラは gcc ver3.2 か 3.4.2 みたいですけど。 そちらは何をお使いで? |
|---|---|
| 種類:補足要求 どんな人:一般人 自信:参考意見 |
|
| |
回答日時:08/04/08 07:12 回答番号:No.3 |
|
| この回答への補足 | ありがとうございます。 失礼しました。 こちらの環境はVC++2008 Express Editionです。 cygwinでgcc 3.4.4で同じコードをコンパイルして動かすと 問題なく動きました。 VCのバグか何かなのでしょうか… それともgccではたまたま動いているだけなのでしょうか。 |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |
回答 |
|
| 回答者:episteme | > const char* c_str = str_stream.str().c_str(); str_stream.str() で一時的に作られた string の寿命が 極めて短く、c_str() が評価された直後にデストラクト されているのでしょうね。 |
|---|---|
| 種類:回答 どんな人:専門家 自信:自信あり |
|
| |
回答日時:08/04/08 06:46 回答番号:No.2 |
|
| この回答への補足 | 回答ありがとうございます。 なるほど、つまり、 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 | "aiueo" << 33; "と<< のあいだに 全角スペースはいっとりまっせ〜 これははまるは そのまま貼り付けなかったら解決しませんでしたね |
|---|---|
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| |
回答日時:08/04/08 06:07 回答番号:No.1 |
|
| この回答への補足 | すみません。全角スペースはタイプミスです。 手元のソースでは普通のスペースになっています。 コンパイルは通ることを確認しています。 失礼しました。 全角スペース問題ではないようです。 よくわからないのは、以下のようにするとうまく動くことです。 std::string moji = str_stream.str(); const char* c_str = moji.c_str(); どうして、 const char* c_str = str_stream.str().c_str(); と一行でまとめて書くとうまくいかないのでしょうか。 |
| この回答へのお礼 | この回答にお礼をつける(質問者のみ) |