为什么在赋值运算符中我们需要返回*this,而一般情况下(而不是&this)我们想要返回对象的引用?

4

我正在学习C++和指针,之前以为已经理解了指针,但看到这个后我就有点糊涂了。

在一侧,星号(*)操作符用于解引用,也就是返回指向的地址中存储的值,而&操作符则相反,它返回值在内存中的存储地址。

现在我正在阅读关于赋值重载的内容,它说“我们返回*this,因为我们想返回对象的引用”。尽管从我所读的内容来看,*this实际上返回的是this的值,如果我们想要返回对象的引用,实际上应该返回&this

这是怎么回事呢?我猜我可能缺少了什么,因为我没有在其他地方找到这个问题的答案,但根据*解引用、&获取引用的逻辑,这个解释似乎完全相反。

例如:

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

this 是指向当前对象的指针。因此,使用 指针 运算符 &(例如 &this)将给我们一个指向对象的指针的指针(在您的情况下类型为 A**)。您需要使用解引用运算符 * 来获取对象本身。 - Some programmer dude
*this 解引用 this 指针,给出当前对象。请记住,this 是一个指针而不是一个对象。根据上下文,& 有多个含义。它可以是一个引用或返回地址。 - drescherjm
相关:https://dev59.com/BlsV5IYBdhLWcg3w8ytf - drescherjm
4个回答

3
这是一个指针,它保留了当前对象的地址。因此,像*this这样解除引用指针,您将获得当前对象本身的左值。展示类的复制赋值运算符的返回类型为A&。因此,返回表达式*this会返回对当前对象的引用。
根据C++ 17标准(8.1.2 This)
引用的关键字this表示指向调用非静态成员函数(12.2.2.1)或评估非静态数据成员初始化程序(12.2)的对象的指针。
请考虑以下代码片段作为简化示例。
int x = 10;

int *this_x = &x;

现在要返回对象的引用,您需要使用表达式*this_x,例如:
std::cout << *this_x << '\n';

1

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

&this,如果合法,将是指向当前对象的指针的指针。但这是非法的,因为 this(指针本身)是一个临时对象,你不能使用 & 取地址。

更有意义的问题是为什么我们不使用 return this;

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

int x = 42;

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

因此,类似地:
int *f1() return {return &x;}
int &f1() return {return  x;}

1

&在不同的上下文中有多种含义。在C语言中,当它单独使用时,它可以是按位与运算符或者是某个符号引用的地址。

在C++中,当它出现在类型名称后面时,它还表示接下来的内容是该类型对象的引用

这意味着如果您输入:

int     a = 0;
int &   b = a;

b将成为事实上的a的别名。

在您的示例中,operator=被设置为返回类型为A的对象(而不是指向它的指针)。这将被上层函数视为这样处理,但实际返回的是一个现有对象,更具体地说是调用此成员函数的类的实例。


0

一个简单的助记符是,*& 运算符匹配你要转换的东西的类型语法,而不是你要转换到的东西:

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

在表达式中,foofoo& 之间没有实质性的区别,因此我可以说 *foo* 转换为 foo,但上面的版本更容易记住。

C++继承了C的类型语法,而C的类型语法是根据使用它们的表达式语法命名的,而不是创建它们的语法。数组写作foo x[...],因为你通过访问元素来使用它们,指针写作foo *x,因为你通过解引用它们来使用它们。指向数组的指针写作foo (*x)[...],因为你需要先解引用它们,然后再访问元素,而指针数组写作foo *x[...],因为你需要先访问元素,然后再解引用它。人们不喜欢这种语法,但它是一致的。

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

this是一个指针的原因也纯粹是历史原因:this在引入引用之前被添加到C++中。但由于它是一个指针,而你需要一个引用,所以你必须使用*来去掉*


foofoo&之间没有实质性的区别”,嗯,表达式不能具有引用类型 - HolyBlackCat
@HolyBlackCat 或许你同意我的观点,但如果不是的话:我认为你提供的段落支持了我的说法。如果 foofoo& 不同,它们需要在进一步的分析中保留这种区别。但由于它们没有区别,他们可以通过选择一个符号来简化它,他们选择了 foo - benrg
是的,如果我表达不清楚,我同意你的观点。 - HolyBlackCat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接