11

复制赋值运算符具有通常的签名:

    my_class & operator = (my_class const & rhs);

下面的签名有什么实际用途吗?

    my_class const & operator = (my_class const & rhs);

您只能定义一个或另一个,但不能同时定义两者。

4

7 回答 7

23

使复制赋值的返回类型成为非常量引用的主要原因是它是标准中对“可赋值”的要求。

如果您将返回类型设为const引用,那么您的类将不符合在任何标准库容器中使用的要求。

于 2010-04-15T23:04:23.470 回答
9

不要那样做。它阻止客户端编写类似的内容:

(a = b).non_const_method();

而不是更长的形式:

a = b;
a.non_const_method();

虽然您可能不喜欢速记风格,但真正由库的用户决定他们想要如何编写代码。

于 2010-04-15T21:33:08.853 回答
5

一个反映C++ 中重载赋值运算符的答案:

返回 aconst&仍然允许赋值链:

a = b = c;

但将不允许一些更不寻常的用途:

(a = b) = c;

请注意,这使得赋值运算符具有类似于它在 C 中的语义,其中=运算符返回的值不是左值。在 C++ 中,标准对其进行了更改,因此=运算符返回左操作数的类型,因此结果是左值。但是正如史蒂夫杰索普在对另一个答案的评论中指出的那样,虽然这使得编译器会接受

(a = b) = c;

即使对于内置插件,结果也是内置插件的未定义行为,因为a它被修改了两次,没有中间的序列点。对于带有 an 的非内置函数,可以避免该问题,operator=()因为operator=()函数调用用作序列点。

我认为返回 a 没有问题,const&除非您想特别允许左值语义(并设计类以确保它与这些语义明智地行动)。如果您的用户想要对 的结果做一些不寻常的事情operator=(),我宁愿该类禁止它,而不是希望它偶然而不是设计正确。

还。请注意,当您说:

您只能定义一个或另一个,但不能同时定义两者。

这是因为 C++ 中的函数签名没有考虑返回值类型。但是,您可以有多个operator=()赋值运算符,它们采用不同的参数并返回适合参数类型的不同类型:

my_class& operator=( my_class& rhs);
my_class const& operator=(my_class const& rhs);

我不完全确定这会给你带来什么。在这两种情况下,分配给的对象(可能是返回的引用)都是非常量的,因此没有逻辑理由仅仅因为isconst&的右手边而返回 a 。但也许我错过了一些东西......=const

于 2010-04-15T21:48:32.320 回答
3

Effective C++ 解释说,这会破坏与 C++ 内置类型的兼容性。

你可以用普通int的 s 做到这一点:

(x = y) = z;

所以他的理由是,不管这看起来多么愚蠢,一个人也应该能够对自己的类型做同样的事情。

这个例子在第 2 版中有,虽然在第 3 版中没有了。然而,这句话来自第 3 版,第 10 条仍然说明了同样的情况:

[...] 赋值返回对其左侧参数的引用,这是为类实现赋值运算符时应遵循的约定:

class Widget {
public:
  ...
  Widget& operator=(const Widget& rhs)   // return type is a reference to
  {                                      // the current class
  ...
  return *this;                        // return the left-hand object
  }
  ...
};
于 2010-04-15T21:28:45.890 回答
2

为什么大家都这么痴迷(a = b) = c?这是偶然写的吗?

更改分配的结果可能有一些不可预见的效用。您不只是针对看起来很有趣的虚构示例制定任意规则。从语义上讲,它没有理由应该是const,因此不要将其声明const为词法副作用。

下面是一个有点合理的代码示例,它会因const &分配而中断:

my_class &ref = a = b;
于 2010-04-15T22:23:52.943 回答
0

与 const 的任何其他用法一样,const 是默认值,除非您真的想让用户更改。

于 2010-04-15T21:26:45.767 回答
-1

是的,应该是const。否则客户可以这样做:

class MyClass
{
public:
      MyClass & operator = (MyClass const & rhs);
}

void Foo() {
    MyClass a, b, c;
    (a = b) = c; //Yikes!
}
于 2010-04-15T21:26:37.733 回答