这是我的代码:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class TestLog: public std::stringstream
{
public:
~TestLog()
{
cout << (str()) << endl; // Why does this print an address ?
}
};
int main()
{
TestLog() << "Hello World!"; //test 1 print an address
stringstream ss;
ss << "Hello World!";
cout << (ss.str()) << endl; //test 2 print a string
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并输出:
0x401b90
你好,世界!
编译器信息:
g ++(GCC)4.8.5 20150623(Red Hat 4.8.5-11)
在我看来,(a)std :: stringstream的str()方法返回一个字符串.(b)std :: cout是std :: ostream的对象.因此,两个测试都将调用ostream的相同运算符函数并打印相同的"Hello world".但测试1打印一个地址,测试2打印正确的"Hello world".
我怎么了 ?谢谢.
ss << "Hello World!";解决了对以下重载的调用(本页#2):
template <class Traits>
std::basic_ostream<char, Traits> &std::operator << (
std::basic_ostream<char, Traits> &os, char const *s
);
Run Code Online (Sandbox Code Playgroud)
此重载将字符串文字衰减为a char const *,然后将其打印出来.
为了搅拌泥浆,我们可以尝试以下代码段:
TestLog tl;
tl << "Hello World!";
Run Code Online (Sandbox Code Playgroud)
这个也将解决上面的重载,并打印Hello World!.那是因为tl是一个左值,它可以绑定到非const左值引用的第一个参数.
在你的例子中,TestLog()是一个右值 - 这个过载无法匹配!因此,选择另一个重载(这里#7):
std::basic_ostream &std::basic_ostream::operator << (void const *value);
Run Code Online (Sandbox Code Playgroud)
这一个是成员函数重载,并且已经继承自std::stringstream.即使您无法将非const引用绑定到右值,也可以const在右值上调用非成员函数.所以这个重载是一个有效的匹配,并且它被选中 - 打印文字的地址就好像它是任何旧指针一样.
C++ 11为解决这个问题带来了新的重载,在#3处可见:
template <class CharT, class Traits, class T>
std::basic_ostream<CharT, Traits> &operator << (
basic_ostream<CharT, Traits> &&os, T const &value
);
Run Code Online (Sandbox Code Playgroud)
T const &char const[N]完全匹配文字的类型,因此排名高于void const *重载.作为第一个参数的rvalue引用绑定到临时就好了.
命名的右值引用被认为os << value;是左值,因此该函数可以再次调用trampoline返回到左值流的重载集.因此,在C++ 11及更高版本中,两行都打印出来Hello World!.
| 归档时间: |
|
| 查看次数: |
562 次 |
| 最近记录: |