关于智能指针中解引用和成员选择运算符的定义

Regarding definition of dereferencing and member selection operators in smart pointer

在智能指针实现中,解引用运算符和成员选择运算符总是定义如下。

T& operator* () const     // dereferencing operator
{
    return *(m_pRawPointer); 
}

T* operator->() const     // member selection operator
{
    return m_pRowPointer;
}

不太明白为什么前者是引用返回,后者是指针返回。只是为了区分他们还是其他一些原因? 更具体地说,我可以通过指针取消引用运算符 returns,而另一个 returns 通过引用吗?

通过引用取消引用运算符 returns 和通过指针选择成员选择运算符 returns 的原因是为了将使用智能指针的语法与使用原始指针的语法对齐指针:

int* p = new int(42);
*p = 7;

std::unique_ptr<int> p(new int(42));
*p = 7;

您完全可以将取消引用运算符 return 设为您喜欢的任何内容:

struct IntPtr {
    int* p;

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

但是当用户不得不写时,这会让他们感到很困惑:

IntPtr p{new int{42}};
**p = 7;

箭头运算符有点不同,因为 [over.ref]:

An expression x->m is interpreted as (x.operator->())->m

所以你必须 return 一些你可以调用 ->m 的东西,否则你只会得到一个错误,比如 (from gcc):

error: result of 'operator->()' yields non-pointer result

why the former is returned by reference

所以表达式 *thing 给出一个 lvalue 表示类型 T 的对象,就像 thing 是一个指针。

the latter is returned by pointer

因为语言就是这样指定的。请注意,您永远不会直接使用 -> 的结果,而是始终使用 thing->member 形式的表达式。

如果 thing 是 class 类型,则通过调用 operator-> 对其进行评估,然后将 ->member 应用于其结果。为了支持它,它必须 return 一个指针,或者另一个 class 也重载 operator->.

的类型

can I make dereferencing operator returns by pointer

是的,但这会让人感到困惑,因为它的行为与将相同的运算符应用于指针不同。您必须说 **thing 才能访问 T.

while the other one returns by reference

不,因为这会破坏语言关于重载运算符应该如何工作的内置假设,使其无法使用。