关于 std::ends
连续好几天看你们在讨论 std::ends,似乎你们都明白它是输出'\0',后面你们的争论我就看不懂了,也没细看。在上世纪C++98之前,<strstream>中有个std::ostrstream。现在已经被<sstream>中的std::ostringstream给替换了。
std::ostrstream s;
s << "abc";
char* p = s.str(); // 冻结缓冲区(因为返回的是一个指针),并返回 'a','b','c'(注意尾部没有'\0') 这样一个序列的起始地址.
// std::cout << p; 不能这么做,因为 p 不是指向以null结尾的字符串(可以这么做 std::cout.write(s.str(), s.pcount()))
// 正确的做法是解冻后,尾部加个'\0',让它成为以null结尾的字符串
s.freeze(false);
s << ends;
std::cout << s.str(); // 这时是正确的,返回序列 'a','b','c','\0'
s.freeze(false); // 别忘了解冻,否则会内存泄漏
简而言之,std::ostrstream::str() 并不主动在缓冲区添加'\0',所以要想它返回一个null结尾的字符串,用户得自己向缓冲区输出std::ends。s << "abc";
char* p = s.str(); // 冻结缓冲区(因为返回的是一个指针),并返回 'a','b','c'(注意尾部没有'\0') 这样一个序列的起始地址.
// std::cout << p; 不能这么做,因为 p 不是指向以null结尾的字符串(可以这么做 std::cout.write(s.str(), s.pcount()))
// 正确的做法是解冻后,尾部加个'\0',让它成为以null结尾的字符串
s.freeze(false);
s << ends;
std::cout << s.str(); // 这时是正确的,返回序列 'a','b','c','\0'
s.freeze(false); // 别忘了解冻,否则会内存泄漏
程序代码:
#include <iostream> #include <strstream> int main() { std::ostrstream s; // 动态缓冲区 s << “abc" << std::ends; std::cout << s.str() << '\n'; s.freeze(false); }
C++98时新的 std::ostringstream 就没这些破事,不需要冻结缓冲区,也不需要std::ends
程序代码:
#include <sstream> #include <iostream> int main() { std::ostringstream s; s << "abc"; // 不需要,也不应该添加 std::ends std::cout << s.str() << '\n'; // 不需要冻结缓冲区,因为 std::ostringstream::str() 返回的是一个std::string类型的缓冲区副本 }
-------
我又看了一下你们的讨论,似乎不是在纠结 std::ends,而是 一个说putchar('\0')是可以的,一个说putchar('\0')是没意义的。