为什么我们在 asignment 运算符中返回 *this,而当我们想返回对对象的引用时,通常(而不是 &this)?

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

提问人: 提问时间:2/28/2022 更新时间:2/28/2022 访问量:706

问:

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

一方面,asterix(*) 运算符是反引用的,这意味着它返回值指向的地址中的值,而 & 号运算符则相反,并返回该值在内存中存储的地址。

现在读到赋值重载,它说“我们返回是因为我们想要返回对对象的引用”。尽管从我读到的内容实际上返回了 this 的值,并且如果我们想返回对对象的引用,实际上在逻辑上应该返回。*this*this&this

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

例如:

struct A {
  A& operator=(const A&) {
    cout << "A::operator=(const A&)" << endl;
    return *this;
  }
};
C++ 赋值运算符

评论

0赞 Some programmer dude 2/28/2022
this是指向当前对象的指针。因此,使用指针运算符 (like ) 将为我们提供指向对象的指针的指针(在您的例子中为 类型 )。您需要使用取消引用运算符来获取对象本身。&&thisA***
0赞 drescherjm 2/28/2022
*this取消引用 this 指针,为您提供当前对象。请记住,这是一个指针,而不是一个对象。根据上下文,具有 1 个以上的含义。它可以是引用,也可以是返回的地址。this&
0赞 drescherjm 2/28/2022
相关新闻: https://stackoverflow.com/questions/35594378/address-of-operator-vs-reference-operator

答:

3赞 Vlad from Moscow 2/28/2022 #1

this是保留当前对象地址的指针。因此,像您一样取消引用指针将获得当前对象本身的左值。所呈现类的复制赋值运算符的返回类型是 。因此,返回表达式时,您将返回对当前对象的引用。*thisA&*this

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

1 关键字 this 命名指向对象的指针,该对象的对象 调用非静态成员函数 (12.2.2.1) 或非静态数据 评估成员的初始值设定项 (12.2)。

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

int x = 10;

int *this_x = &x;

现在,要返回对对象的引用,您需要使用表达式,例如*this_x

std::cout << *this_x << '\n';
1赞 Obsidian 2/28/2022 #2

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

在 C++ 中,在类型名称之后,它还意味着后面的内容是对此类对象的引用

这意味着您输入:

int     a = 0;
int &   b = a;

... 将成为事实上的别名。ba

在您的示例中,用于返回 A 类型的对象(而不是指向它的指针)。uppers 函数将以这种方式看到这一点,但实际返回的是一个现有对象,更具体地说,是调用此成员函数的类的实例。operator=

1赞 HolyBlackCat 2/28/2022 #3

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

&this如果它是合法的,将是指向当前对象的指针到指针。但这是非法的,因为(指针本身)是一个临时对象,你不能获取那些带有 .this&

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

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

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

所以,同样:

int *f1() return {return &x;}
int &f1() return {return  x;}
0赞 benrg 2/28/2022 #4

您可以使用的简单助记符是 and 运算符与要转换的事物的类型语法匹配,而不是要转换为的事物:*&

  • *将 A 转换为foo*foo&
  • &将 A 转换为foo&foo*

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

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

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

原因是指针也是纯粹的历史:在引用之前被添加到 C++。但是由于它是一个指针,并且您需要一个引用,因此您必须使用来摆脱 .thisthis**

评论

0赞 HolyBlackCat 2/28/2022
foo 和 foo 之间没有有意义的区别&嗯,表达式不能有引用类型
0赞 benrg 2/28/2022
@HolyBlackCat 也许你同意我的观点,但如果不是:我认为你链接的段落支持我所说的话。如果和不同,则需要在进一步分析中保留区别。既然不是,他们可以通过选择一种符号来简化它,他们选择了 .foofoo&foo
0赞 HolyBlackCat 2/28/2022
是的,对不起,如果我不清楚,我同意你的看法。