繁体   English   中英

为什么 operator = 返回 *this?

[英]Why does operator = return *this?

假设我想覆盖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

然后在我对operator =的实现中,我有这样的东西:

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

不要介意实施,它已经可以正常工作了。

我担心的是当你return *this时会发生什么? 我知道它返回对对象的引用,但会发生这种情况吗?

p2 = &p1

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

因为那句话基本上是:

p3.operator=(p2.operator=(p1));

如果p2.operator=(...)没有return *this你将没有任何意义传递给p3.operator=(...)

p2 = p1p2.operator=(p1)的简写。 它只是调用您的operator=函数,该函数返回对p2的引用,然后您将忽略它。 为了清楚起见,我们称它为assign而不是operator=

Poly& Poly::assign(const Poly &source) {
    .
    .
    .
    return *this;
}

现在代替p2 = p1 ,你会写

p2.assign(p1);

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

p3.assign(p2.assign(p1));

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

p3 = (p2 = p1);

但由于赋值是右结合的,这也可以写成

p3 = p2 = p1;

这种能够同时进行多项赋值的形式最初来自 C,并通过在operator=()中返回*this的约定保留在 C++ 中。

如果您无论如何都不需要链式赋值(如其他答案所示),则可能会试图让复制赋值运算符返回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
}

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

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

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

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

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

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

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

只要不违反此 C++ 约定,您就不会遇到麻烦。

当你返回 *this 时会发生什么?

在您的示例( p2 = p1; )中,什么都没有。 该方法将p1复制到p2并返回对调用代码不使用的“this”对象的引用。

p3 = p2 = p1; ,第一个调用是p2 = p1 ,它将p1复制到p2并返回对p2的引用。 然后调用代码从该对p2的引用复制到p3 (并忽略返回的对p3的引用)。

(顺带一提:您的单元测试是否确保p1 = p1正常工作?很容易忘记这种情况!)

返回对目标对象的引用允许赋值链接(级联),并且类内的重载运算符遵循右关联(单击此处了解详细的运算符重载规则)

Poly a, b, c;
a = b = c;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM