运算符链在C++中是如何发生的

How does operator chaining happen in C++?

本文关键字:何发生 C++ 运算符      更新时间:2023-10-16

我这里有一个完全基本的C++问题。

#include <iostream>
using namespace std;
int main() {
    int a = 255;
    cout << hex << a << endl; // <-----
}

在上面的代码段中,std::cout语句是如何链接的?

我知道 cout 的实现会返回对cout对象的引用以允许发生链接,因此它应该执行为:

(((cout << hex) << a) << endl)

即等同于这些,按

  1. cout << hex
  2. cout << a
  3. cout << endl

但情况并非如此,因为a的值需要以某种方式转换为hex形式!

编译器实际上如何链接运算符以实现转换?

你说得对,这正是它的工作原理。 hex只有一个特殊类型,当传递给其operator<<函数时,该类型会更改cout对象的内部状态。然后,内部状态确定如何处理通过operator<<传递给cout的任何未来值。

std::hex恰好是一个函数。 但是,cout << hex不会这样调用十六进制函数:它将指向十六进制函数的指针传递给ostreamoperator<<重载,该重载接受具有特定签名的函数指针。 然后通过该函数指针从运算符实现内部调用hex(),并据我所知从那里修改ostream对象。

以下是

通常如何实现hex

inline ios_base&
hex(ios_base& __base)
{
    __base.setf(ios_base::hex, ios_base::basefield);
    return __base;
}

如您所见,hex 本身不执行任何转换:相反,它在基本流中设置一个选项,以使用十六进制打印稍后传入的数字。

编辑(回复评论(

正如哈马尔正确指出的那样,难题的另一部分是如何称呼hex(ios_base& __base)。具有以下签名的 << 运算符重载:

ostream& operator <<(ostream& (*)(ostream&))

这种重载是流操纵器的基本实现细节。正是这种重载召唤了hex,并让它发挥它的"魔力"(当然,这对你来说听起来不应该再像魔术了(。

std::hex实际上在std::cout对象中设置了一个标志,该标志将一直持续到重置IIRC。operator<<本身从左到右计算,因此您的括号是正确的。

在我看来,十六进制只是一个包对象,对 cout 对象有副作用。在此之后,cout 将仅输出十六进制值。

std::hex 是一个更改 std::ostream 对象状态的函数。 http://www.cplusplus.com/reference/iostream/manipulators/hex/