当作为 class 的成员函数重载时,取消引用运算符 (*) 如何工作?

How does dereference operator (*) work when overloaded as a member function of a class?

当我在 operator overloading 上查找书籍和堆栈溢出文章时,我发现了以下内容:

When an overloaded operator is a member function, this is bound to the left-hand operand. Member operator functions have one less (explicit) parameter than the number of operands.

(Addison Wesley,C++ 入门)

所以我的问题是,由于 *(取消引用)运算符没有任何左操作数,它如何获取其参数(即对象本身或 this)?

前缀 * 对其后的操作数进行运算。

对于用户定义的 operator* 表示为成员函数,这是 this 表达式引用的对象。

#include <iostream>
using namespace std;

struct S
{
    auto operator*() const -> char const* { return "Hi there!"; }
};

auto main()
    -> int
{ cout << *S() << endl; }

结果:

Hi there!

取消引用运算符与重载运算符的工作方式与普通运算符的工作方式完全相同。

int foo(int *p)
{
     return *p;
}

在语句return *p;中,取消引用运算符应用于指针p。右边传给它:

作为重载运算符,它的工作方式相同。

class bar {

     int *some_internal_ptr;

public:
     int operator*() const {
          return *some_internal_ptr;
     }

     // Other class members and methods...
};

int foo(bar p)
{
     return *p;
}

* 运算符的右侧是带有 operator*` 成员的 class 时,它作为 class 的重载方法被调用,与任何其他成员,以解决取消引用。

这是因为用法相同,这就是为什么许多 C++ 库算法与指针或 C++ 库运算符一起工作得同样好。例如,std::copy() 可以 实现如下(我正在修剪一些与这里无关的无关复杂性):

template<typename iter_type>
iter_type copy(iter_type b, iter_type e, iter_type t)
{
    while (b != e)
    {
       *t=*b;
       ++t;
       ++b;
    }
    return t;
}

您可以将本机指针传递给 std::copy,或者像迭代器一样传递 classes,使用重载的 * 运算符,并且因为重载的 * 运算符用于与普通 * 运算符相同的语法,相同的算法也适用于重载运算符。

对于所有前缀一元运算符,它对其后面的操作数进行运算。

As an added question would there be any difference in how the overloaded * operator is used if it is defined as a non-member function vs a member function

在大多数情况下,不,除了非成员函数不能访问那个class的私有成员,如果成员函数和非成员函数都存在,编译器需要使用overload resolution to pick the higher rank function, if there're no better function, it's ambigious call, see ADL

对于可靠的来源,您可以查看 operator overloading,或者,更好的是,标准 C++ 中的第 13.5.1 节 [over.unary]:

A prefix unary operator shall be implemented by a non-static member function (9.3) with no parameters or a non-member function with one parameter. Thus, for any prefix unary operator @, @x can be interpreted as either x.operator@() or operator@(x). If both forms of the operator function have been declared, the rules in 13.3.1.2 determine which, if any, interpretation is used. See 13.5.7 for an explanation of the postfix unary operators ++ and --. 2 The unary and binary forms of the same operator are considered to have the same name. [ Note: Consequently, a unary operator can hide a binary operator from an enclosing scope, and vice versa. —end note ]

同时有会员和非会员的选择,见13.3.1.2 [over.match.oper]