为什么operator = return * this?

时间:2016-01-02 05:19:57

标签: 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

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

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

不介意实施,它已经正常工作。

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

p2 = &p1

5 个答案:

答案 0 :(得分:14)

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=(...)

答案 1 :(得分:5)

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,并通过在*this中返回operator=()的惯例保存在C ++中。

答案 2 :(得分:4)

如果您不需要链接赋值(如其他答案所示),可能会想让复制赋值运算符返回$stmt = $conn->prepare("select * from locations"); $stmt->execute(); $result = $stmt->fetchAll(); if ($result) { echo json_encode($result); } 。毕竟,链式作业通常难以阅读和理解,因此不允许将它们视为改进

然而,一个经常被忽视的方面是void意味着您的类型不再支持CopyAssignable concept,这需要void operator=(Poly& const)返回类型。

不符合T&概念的类型无法正式用于某些标准容器操作,例如CopyAssignable,这意味着以下看似无辜的代码会产生不确定的行为,甚至虽然它可能运行得很好:

std::vector::insert

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

  

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

     

(...)用于实例化a时用作模板参数的类型   模板组件,如果类型上的操作没有实现   适用要求的语义子条款(...)。

当然,正是因为未定义行为的,允许编译器忽略错误并使程序运行良好,与明显预期的行为相匹配。但并不要求这样做。

您还应该考虑到无法预测#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 } 类型的所有未来用途。有人可能会写一些模板函数,例如:

Poly

此功能不适用于您的template <class T> void f(T const& t) { T t2; T t3 = t2 = t; // ... } 课程。

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

答案 3 :(得分:2)

  

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

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

p3 = p2 = p1;等代码中,第一次调用为p2 = p1,将p1复制到p2并返回对p2的引用。然后,调用代码从该引用复制到 - p2p3(并忽略对返回的p3的引用。)

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

答案 4 :(得分:0)

返回对目标对象的引用允许赋值链接(级联),并且类中的重载运算符遵循右关联(单击here以获取详细的运算符重载规则)

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