为什么调用cout.operator<<(const char*)会打印地址而不是字符串?

29

我正在探索C++中的ostream类。我困惑于对字符串和整数数据类型使用cout时奇怪的输出。

当传递一个整数或浮点值时,输出正好是我传递的值。例如,cout.operator<<(10);打印10。但是当传递一个字符串作为参数时,它会打印一些十六进制值:

#include <iostream>
#include <string>

using namespace std;

int main() {
        const char* str = "aia";
        cout.operator<<(str);
        return 0;
}

输出:0x4007e0


5
你为什么直接使用 operator<<?你想要做什么? - Nicol Bolas
@NicolBolas 我怀疑他们不知道该怎么做。 - john
3
我正在尝试理解运算符的级联实际是如何工作的。 - Pranjal Kaler
1
假设您没有使用那种形式的operator<<的特殊原因,只需使用cout << str;即可看到您期望的输出。 - john
1
我尝试了一下,它打印了字符串,但我的问题是为什么它可以打印其他数据类型的相同结果时,为什么会打印一些十六进制值。 - Pranjal Kaler
显示剩余3条评论
2个回答

30
当您执行cout.operator<<(str)时,您调用了coutoperator <<成员函数。如果我们查看成员函数重载cout有哪些,我们会发现:
basic_ostream& operator<<( short value );
basic_ostream& operator<<( unsigned short value );

basic_ostream& operator<<( int value );
basic_ostream& operator<<( unsigned int value );

basic_ostream& operator<<( long value );
basic_ostream& operator<<( unsigned long value );

basic_ostream& operator<<( long long value );
basic_ostream& operator<<( unsigned long long value );

basic_ostream& operator<<( float value );
basic_ostream& operator<<( double value );
basic_ostream& operator<<( long double value );

basic_ostream& operator<<( bool value );

basic_ostream& operator<<( const void* value );

basic_ostream& operator<<( std::nullptr_t );

basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);

basic_ostream& operator<<(
    std::ios_base& (*func)(std::ios_base&) );

basic_ostream& operator<<(
    std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );

basic_ostream& operator<<(
    std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );

如果你注意到了,没有一个适用于const char*的函数,但是有一个适用于const void*的函数。因此,你的const char*会被转换为const void*,并且该函数版本会打印指针所保存的地址。
你需要做的是调用operator<<非成员函数重载,为此你可以使用:
cout << str;

10
始终使用 cout << X,不要直接使用 cout.operator<<(X)operator<<(cout, X)(除非你确有充分的理由这样做)。让编译器基于上下文和数据类型来决定调用哪个函数。 - Remy Lebeau
@RemyLebeau 我已经移除了 operator<<(cout, X) 的调用。正如你所说,他们应该只使用运算符语法。 - NathanOliver

16
问题在于对于某些类型,operator<<作为ostream的成员进行了重载,而对于某些类型,它作为全局函数进行了重载。对于const char*,它是一个全局函数,所以如果你想显式调用运算符函数,你必须写:
operator<<(cout, str);

但对于整数类型,您必须编写

cout.operator<<(num);

你发帖中的代码调用了 const void* 的重载,所以你看到了十六进制数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接