问题描述
我偶然发现了一个我一开始无法解释的奇怪行为(参见 ideone):
I have stumbled on a weird behavior that I just could not explain at first (see ideone):
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::cout << "Reference : "
<< (void const*)"some data"
<< "
";
std::ostringstream s;
s << "some data";
std::cout << "Regular Syntax: " << s.str() << "
";
std::ostringstream s2;
std::cout << "Semi inline : "
<< static_cast<std::ostringstream&>(s2 << "some data").str()
<< "
";
std::cout << "Inline : "
<< dynamic_cast<std::ostringstream&>(
std::ostringstream() << "some data"
).str()
<< "
";
}
给出输出:
Reference : 0x804a03d
Regular Syntax: some data
Semi inline : some data
Inline : 0x804a03d
令人惊讶的是,在最后一次演员表中,我们有地址,而不是内容!
Surprisingly, in the last cast we have the address, and not the content!
为什么会这样?
推荐答案
表达式std::ostringstream()
创建一个临时的,operator<<<
需要const char*
as argument 是一个自由函数,但是这个自由函数不能临时调用,因为函数的第一个参数的类型是std::ostream&
不能绑定到临时对象.
The expressionstd::ostringstream()
creates a temporary, and operator<<
which takes const char*
as argument is a free function, but this free function cannot be called on a temporary, as the type of the first parameter of the function is std::ostream&
which cannot be bound to temporary object.
话虽如此,<<std::ostringstream() <<一些数据"
解析为对打印地址的 void*
重载的成员函数的调用.请注意,可以在临时上调用成员函数.
Having said that, <<std::ostringstream() << "some data"
resolves to a call to a member function which is overloaded for void*
which prints the address. Note that a member function can be invoked on the temporary.
为了调用自由函数,您需要将临时(即右值)转换为左值,这是您可以执行的一个技巧:
In order to call the free function, you need to convert temporary (which is rvalue) into a lvalue, and here is one trick that you can do:
std::cout << "Inline : "
<< dynamic_cast<std::ostringstream&>(
std::ostringstream().flush() << "some data"
).str()
<< "
";
即 std::ostringstream().flush()
返回 std::ostream&
这意味着,现在可以调用自由函数,传递返回的引用作为第一个论点.
That is, std::ostringstream().flush()
returns std::ostream&
which means, now the free function can called, passing the returned reference as first argument.
另外,你不需要在这里使用 dynamic_cast
(这很慢,因为它是在运行时完成的),因为对象的类型是非常已知的,所以你可以使用static_cast
(它在编译时完成得很快):
Also, you don't need to use dynamic_cast
here (which is slow, as it is done at runtime), for the type of the object is pretty much known, and so you can use static_cast
(which is fast as it is done at compile-time):
std::cout << "Inline : "
<< static_cast<std::ostringstream&>(
std::ostringstream().flush() << "some data"
).str()
<< "
";
应该可以正常工作.
这篇关于std::ostringstream 打印 c 字符串的地址而不是其内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!