ostream链接,输出顺序

Low*_*eek 10 c++ iostream chaining

我有一个函数,它将ostream引用作为参数,将一些数据写入流,然后返回对同一个流的引用,如下所示:

#include <iostream>

std::ostream& print( std::ostream& os ) {
  os << " How are you?" << std::endl;
  return os;
}

int main() {
  std::cout << "Hello, world!" << print( std::cout ) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

 How are you?
Hello, world!0x601288
Run Code Online (Sandbox Code Playgroud)

但是,如果我将链接表达式分成两个语句,就像这样

int main() {
  std::cout << "Hello, world!";
  std::cout << print( std::cout ) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

然后我至少在输出中得到正确的顺序,但仍然得到一个十六进制值:

Hello, world! How are you?
0x600ec8
Run Code Online (Sandbox Code Playgroud)

我想了解这里发生了什么.正常函数是否优先operator<<,这就是输出顺序反转的原因?编写将数据插入到一个ostream但也可以链接的函数的正确方法是什么operator<<

Naw*_*waz 5

根据C++标准,未指定代码的行为.

说明

以下(std::endl为简单起见,我删除了)

std::cout << "Hello, world!" << print( std::cout ); 
Run Code Online (Sandbox Code Playgroud)

相当于:

operator<<(operator<<(std::cout, "Hello, World!"), print(std::cout));
Run Code Online (Sandbox Code Playgroud)

这是一个函数调用,传递两个参数:

  • 第一个参数是: operator<<(std::cout, "Hello, World!")
  • 第二个论点是: print(std::cout)

现在,标准没有指定参数的计算顺序.它没有具体说明.但是你的编译器似乎首先评估第二个参数,这就是它打印"你好吗?"的原因.首先,将第二个参数计算为type的值std::ostream&,然后将其传递给上面显示的调用(该值是对象std::cout本身).

为什么十六进制输出?

你得到十六进制输出,因为第二个参数的计算结果是std::cout,它被打印为十六进制数,因为std::cout隐式转换为void*类型的指针值,这就是为什么它被打印为十六进制数.

试试这个:

void const *pointer = std::cout; //implicitly converts into pointer type!
std::cout << std::cout << std::endl;
std::cout << pointer << std::endl;
Run Code Online (Sandbox Code Playgroud)

它将为两者打印相同的值.例如,ideone的这个例子打印出这个:

0x804a044
0x804a044 
Run Code Online (Sandbox Code Playgroud)

还要注意我没有使用显式转换 ; 而std::cout隐式地转换成指针类型.

希望有所帮助.


编写将数据插入到一个ostream但也可以链接的函数的正确方法是什么operator<<

什么时候取决于链接的意思?显然,以下内容不起作用(如上所述):

std::cout << X << print(std::cout) << Y << Z; //unspecified behaviour!
Run Code Online (Sandbox Code Playgroud)

不管你怎么写print().

然而,这是明确定义的:

print(std::cout) << X << Y << Z; //well-defined behaviour!
Run Code Online (Sandbox Code Playgroud)