为什么operator = return*this?

Jud*_*nga 10 c++ assignment-operator copy-assignment

说我想覆盖operator =所以我可以做类似的事情

Poly p1;  // an object representing a polynomial
Poly p2;  // another object of the same type    
p2 = p1;  // assigns all the contents of p1 to p2
Run Code Online (Sandbox Code Playgroud)

然后在我的实现中operator =,我有这样的事情:

Poly& Poly::operator=(const Poly &source) {
    // Skipping implementation, it already works fine…
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

不介意实现,它已经正常工作.

我关心的是你什么时候会发生什么return *this?我知道它返回对象的引用,但这是怎么回事?

p2 = &p1
Run Code Online (Sandbox Code Playgroud)

Pau*_*ans 16

return *this可以编写正常的复合C++ =语句,如:

Poly p1; //an object representing a polynomial
Poly p2;
Poly p2;

// ...

p3 = p2 = p1;  //assigns all the contents of p1 to p2 and then to p3
Run Code Online (Sandbox Code Playgroud)

因为该陈述基本上是:

p3.operator=(p2.operator=(p1));
Run Code Online (Sandbox Code Playgroud)

如果p2.operator=(...)没有,return *this你没有任何意义可以传递进去p3.operator=(...).


Chr*_*ckl 7

void如果您无论如何都不需要链式赋值(如其他答案中所示),则可能会试图让复制赋值运算符返回。毕竟,链式作业通常难以阅读和理解,因此不允许它们被视为一种改进

然而,一个经常被忽视的方面是这void operator=(Poly& const)意味着您的类型将不再满足需要返回类型的CopyAssignable概念T&

不满足该CopyAssignable概念的类型不能正式用于某些标准容器操作,例如std::vector::insert,这意味着以下看似无辜的代码段会产生未定义的行为,即使它可能运行得非常好:

#include <vector>

struct Poly
{
    void operator=(Poly const&) {} // Poly is not CopyAssignable
};

int main()
{
  std::vector<Poly> v;
  Poly p;
  v.insert(v.begin(), p); // undefined behaviour
}
Run Code Online (Sandbox Code Playgroud)

正如 C++ 标准在 § 17.6.4.8/2.3 中解释的那样,它讨论了对使用标准库的程序的约束:

(...)在以下情况下效果未定义

(...) 对于在实例化模板组件时用作模板参数的类型如果对类型的操作未实现适用的需求子条款 (...)的语义

当然,正是由于未定义的行为,编译器才被允许忽略错误并使程序表现良好,与明显预期的行为相匹配。但并不是必须这样做。

您还应该考虑到您无法预测您的Poly类型的所有未来用途。有人可能会编写一些模板函数,例如:

template <class T>
void f(T const& t)
{
    T t2;
    T t3 = t2 = t;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

此功能将不适用于您的Poly班级。

只要不要违反这个 C++ 约定,你就不会遇到麻烦。


Vau*_*ato 6

p2 = p1是一个简写p2.operator=(p1).它只是调用你的operator=函数,它返回一个引用p2,然后你忽略它.为了说明这一点,让我们把它assign代替operator=:

Poly& Poly::assign(const Poly &source) {
    .
    .
    .
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

而不是p2 = p1,你会写

p2.assign(p1);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用的结果将assign被忽略,但您不必忽略它.例如,你可以写:

p3.assign(p2.assign(p1));
Run Code Online (Sandbox Code Playgroud)

使用operator=而不是assign,这变成了

p3 = (p2 = p1);
Run Code Online (Sandbox Code Playgroud)

但由于赋值是右关联的,因此也可以写成

p3 = p2 = p1;
Run Code Online (Sandbox Code Playgroud)

这种能够一次完成多个赋值的形式最初来自C,并且通过返回的约定保存在C++ *thisoperator=().