我偶然发现了一个我最初无法解释的奇怪行为(见ideone):
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::cout << "Reference : "
<< (void const*)"some data"
<< "\n";
std::ostringstream s;
s << "some data";
std::cout << "Regular Syntax: " << s.str() << "\n";
std::ostringstream s2;
std::cout << "Semi inline : "
<< static_cast<std::ostringstream&>(s2 << "some data").str()
<< "\n";
std::cout << "Inline : "
<< dynamic_cast<std::ostringstream&>(
std::ostringstream() << "some data"
).str()
<< "\n";
}
Run Code Online (Sandbox Code Playgroud)
给出输出:
Reference : 0x804a03d
Regular Syntax: some data
Semi inline : some data
Inline : 0x804a03d
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,在最后一次演员表中我们有地址,而不是内容!
为什么会这样 ?
Naw*_*waz 19
表达式std::ostringstream()创建一个临时的,并且operator<<将const char*参数作为自由函数,但是这个自由函数不能在临时函数上调用,因为函数的第一个参数的类型是std::ostream&不能绑定到临时对象的.
话虽如此,<<std::ostringstream() << "some data"解析为调用重载的成员函数void*,打印地址.请注意,可以在临时上调用成员函数.
为了调用自由函数,你需要将临时值(即rvalue)转换为左值,这是你可以做的一个技巧:
std::cout << "Inline : "
<< dynamic_cast<std::ostringstream&>(
std::ostringstream().flush() << "some data"
).str()
<< "\n";
Run Code Online (Sandbox Code Playgroud)
也就是说,std::ostringstream().flush()返回std::ostream&意味着,现在可以调用自由函数,将返回的引用作为第一个参数传递.
此外,你不需要在dynamic_cast这里使用(这很慢,因为它在运行时完成),因为对象的类型是众所周知的,所以你可以使用static_cast(这在编译时很快就完成了 -时间):
std::cout << "Inline : "
<< static_cast<std::ostringstream&>(
std::ostringstream().flush() << "some data"
).str()
<< "\n";
Run Code Online (Sandbox Code Playgroud)
应该工作得很好.
临时不能绑定到对非const形式参数的引用.
因此,非会员<<不被接听.
你会得到void*版本.
C++ 11通过添加非成员rvalue流插入器函数来修复此问题,
C++
11§27.7.3.9右值流插入
[ostream.rvalue] 1 效果: 2 返回:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
os << x
os
干杯和hth.