注册 登录
编程论坛 C++教室

关于 std::ends

rjsp 发布于 2020-03-18 09:43, 3537 次点击
连续好几天看你们在讨论 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
程序代码:
#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')是没意义的。
8 回复
#2
纯蓝之刃2020-03-18 10:22
我只是静静的看着
#3
lin51616782020-03-18 11:02
ends 本身没什么值得讨论了
我都贴截图出来了
一个putchar('\0')
可能没输出 可能输出空格 甚至可能输出a

我只是在解释 为什么cout<<ends能编译运行但还是错误 这个道理
我发现很多新手都会有 能编译运行就是对的 这样的想法
这需要纠正 尤其是C/C++ 有很多未定义行为
这些东西能编译运行 但还是错误

#4
lin51616782020-03-18 11:04
从你查到的资料来看
ends的确如我所说 根本不是给cout使用的
是给一个废弃类型设计的
现在只是一个历史痕迹 没实际应用价值
使用cout << ends 这样的做法只是自找麻烦
写给新手更是会误人子弟
#5
叶纤2020-03-18 12:14
程序代码:

看看人家的举例多有信服力度,
你非要拿着未初始的变量和我举例,我怎么看都不明白呀就知道楼上认为ends不是给cout用的,但是和cout n没关系啊
还好我昨天科普点I/O的知识楼主的代码还是可以看懂的
程序代码:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    int n;
    cout << n;   
    return 0;
}


#6
叶纤2020-03-18 12:24
回复 楼主 rjsp
那std :: basic_ostream。和cout,cerr是什么关系啊,
算了,我有时间的时候认真看看io的知识点,估计就能找到了

[此贴子已经被作者于2020-3-18 12:41编辑过]

#7
rjsp2020-03-18 12:54
以下是引用叶纤在2020-3-18 12:24:29的发言:

那std :: basic_ostream。和cout,cerr是什么关系啊,
算了,我有时间的时候认真看看io的知识点,估计就能找到了
cout、clog、cerr 都是 std::basic_ostream<char> 类型的变量。

cout 对应于C语言的stdout带缓存
clog 对应于C语言的stderr带缓存
cerr 对应于C语言的stderr不带缓存
#8
叶纤2020-03-18 13:24
我把每一个代码都当成解密游戏,等我把这个谜题解开了再答谢lin5161678大大,r版主的代码就是高级boss怎么都解不开,就比如
程序代码:

std::string foo( const std::string& s, size_t offset )
{
    if( offset < s.size() )
        return string(s, offset);
    return string();
}我把我教材里关于string的知识点都看了,接触了string—view,然后也接触了如签名里一大堆的函数,一时接触的太多怕忘就全写到了签名里,但是就是解不开为什么可以直接返回参数结果没有变,然后就把指针的知识点也一同看了,突然感觉自己等级太低,搞不定boss的代码,自己要不停的刷级才能搞定一条,还好这里可以直接和boss对话,,,,解boss的代码也不是很困难了
#9
ljj25102022-01-11 00:06
1