为什么字符串流运算符<<擦除原始值

时间:2016-01-13 04:19:43

标签: c++

有人可以解释为什么以下代码产生"你&#34!;而不是"你好!"。

int main() {
    std::stringstream ss("hello");
    ss << " you!";
    cout << ss.str() << endl;
}

3 个答案:

答案 0 :(得分:4)

openmode 必须设置ate

这就是你要找的东西:

int main() {
    std::stringstream ss("hello", std::ios_base::out | std::ios_base::ate);
    ss << " you!";
    cout << ss.str() << endl;
}

答案 1 :(得分:3)

获取std::stringstream参数的string constructor

explicit basic_stringstream( const std::basic_string<CharT,Traits,Allocator>& str,
                ios_base::openmode mode = ios_base::in|ios_base::out );

由于您尚未为mode指定任何标记,因此将使用ios_base::in|ios_base::out初始化基础stringbuf。

stringbuf constructor取一个字符串将通过调用str来初始化内部指针,正如您在描述中可以看到mode & ios_base::ate为假,然后任何输出都将写入开头缓冲区。

如果您希望将输出附加到stringstream,您需要在写作之前寻求结束,或者使用stringstream构建ios_base::in|ios_base::out|ios_base::ate

答案 2 :(得分:2)

考虑一下你所写内容的以下微小变化,可能会更清楚:

int main() {
  std::stringstream ss("hello");
  ss << " you";
  cout << ss.str() << endl;
}

Outputyouo

使用std::stringstream初始化std::string时,该字符串将成为streambuffer。但是,stringstream的头部在开头而不是在结尾处初始化。在只编写4个字符而不是5个字符的版本中,hello中的o不会被覆盖,因此您将youo作为缓冲区的最终值。

这种行为就是为什么这段代码prints hello而不是什么:

int main()
{
  std::stringstream ss("hello");
  std::string s;
  ss >> s;
  cout << s << endl;
}

这也是此代码successfully prints 49的原因,而不是任何内容:

int main()
{
  std::stringstream ss("49");
  int x = 0;
  ss >> x;
  cout << x << endl;
}

如果你使用ostream::seekp,你可以在初始化后将位置设置为结束,因此它会like you expected

int main() {
  std::stringstream ss("hello");
  ss.seekp(0, ss.end);
  ss << " you!";
  cout << ss.str() << endl;
}

输出:hello you!