为什么我们在赋值运算符中使用 return *this 而通常(而不是 this)当我们想要 return 对象的引用时?

Why do we return *this in asignment operator and generally (and not &this) when we want to return a reference to the object?

我正在学习 C++ 和指针,在看到这个之前我以为我理解了指针。

一方面,星号 (*) 运算符正在取消引用,这意味着它 returns 值指向的地址中的值,而与号 (&) 运算符则相反,并且returns 值存储在内存中的地址。

现在阅读有关赋值重载的内​​容,它说“我们 return *this 因为我们想要 return 对象的引用”。虽然从我读到的 *this 实际上 return 这个值,实际上 &this 逻辑上应该是 return 如果我们想 return 引用对象。

这怎么加起来?我想我在这里遗漏了一些东西,因为我没有在其他地方找到这个问题,但解释似乎与应该的完全相反,关于 * 取消引用的逻辑,并获得参考。

例如这里:

struct A {
  A& operator=(const A&) {
    cout << "A::operator=(const A&)" << endl;
    return *this;
  }
};

this是一个指针,保存当前对象的地址。所以像 *this 这样取消引用指针你会得到当前对象本身的左值。而呈现的class的复制赋值运算符的return类型是A&。所以 returning 表达式 *this 你是 returning 对当前对象的引用。

根据C++ 17标准(8.1.2本)

1 The keyword this names a pointer to the object for which a non-static member function (12.2.2.1) is invoked or a non-static data member’s initializer (12.2) is evaluated.

将以下代码片段视为一个简化示例。

int x = 10;

int *this_x = &x;

现在 return 对象的引用需要使用表达式 *this_x 例如

std::cout << *this_x << '\n';

& 根据上下文有多种含义。在 C 中单独使用时,I 可以是按位与运算符,也可以是符号引用的地址。

在 C++ 中,在类型名称之后,还意味着紧随其后的是对该类型对象的 引用

这意味着你输入的是:

int     a = 0;
int &   b = a;

b 将成为 事实上 a.

的别名

在您的示例中,operator= 被设为 return 类型 A 的对象(不是指向它的指针)。这将被 uppers 函数以这种方式看到,但实际上 returned 是一个现有对象,更具体地说是调用了该成员函数的 class 的实例。

是的,*this 是(的值?)当前对象。但是指向当前对象的指针是this,而不是&this.

&this如果是合法的,将是pointer-to-pointer到当前对象。但它是非法的,因为 this (指针本身)是一个临时对象,你不能使用 &.

获取地址

问我们为什么不这样做会更有意义return this;

答案是:形成指针需要&,但形成引用则不需要。比较:

int x = 42;
int *ptr = &x;
int &ref =  x;

所以,类似地:

int *f1() return {return &x;}
int &f1() return {return  x;}

您可以使用的一个简单助记符是 *& 运算符匹配您要从 转换的对象的类型语法,而不是你要转换成的东西:

  • *foo* 转换为 foo&
  • &foo& 转换为 foo*

在表达式中,foofoo& 之间没有有意义的区别,所以我可以说 *foo* 转换为 foo,但是上面的版本更容易记住。

C++ 从 C 继承了它的类型语法,C 类型语法以使用它们的表达式语法命名类型,而不是创建它们的语法。数组写成 foo x[...] 是因为您通过访问元素来使用它们,而指针写成 foo *x 是因为您通过取消引用它们来使用它们。指向数组的指针写成 foo (*x)[...] 是因为您通过取消引用它们然后访问元素来使用它们,而指针数组写成 foo *x[...] 因为您通过访问元素然后取消引用它来使用它们。人们不喜欢语法,但它是一致的。

引用是后来添加的,破坏了一致性,因为使用引用的语法与“直接”使用引用对象没有任何区别。因此,您不应该试图理解引用的类型语法。就是这样。

this 是指针的原因也纯粹是历史原因:this 是在引用出现之前添加到 C++ 中的。但是因为它是一个指针,你需要一个引用,你必须使用 * 来摆脱 *.