考虑以下代码片段:
std::stringstream ss;
ss << "hello world!n";
auto a = ss.rdbuf();
std::cout << a; // prints out "hello world!
变量a
是指向std::stringbuf
类型对象的指针。通过GCC9.4将其传递给流输出操作符<<
,输出a
所指向的流缓冲区的内容。
我的问题是:这种行为只是std::stringbuf
在GCC中实现的方式的意外,还是语言标准保证这将始终有效?
std::basic_stringbuf
派生自std::basic_streambuf。Cppreference描述了它的用法:
I/O流对象
std::basic_istream
和std::basic_ostream
,以及从它们派生的所有对象(std::ofstream
,std::stringstream
等),完全是根据std::basic_streambuf
实现的。
那是什么意思?那么,让我们来看看std::basic_istream::operator<<
的重载设置:
basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb );
(10)
表现为
UnformattedOutputFunction
。在构造并检查哨兵对象之后,检查sb
是否为空指针。如果是,执行setstate(badbit)
并退出。否则,从sb
控制的输入序列中提取字符,插入到*this
中,直到满足以下条件之一:
- 文件结束发生在输入序列上;
- 在输出序列中插入失败(此时要插入的字符未被提取);
- 异常发生(在这种情况下异常被捕获)。
如果没有插入字符,执行
setstate(failbit)
。如果在提取时抛出异常,则设置failbit
,如果failbit
在exceptions()
中设置,则重新抛出异常。
所以,是的,标准保证std::cout << ss.rdbuf();
将具有您观察到的效果。