C++ 是否有人发现需要声明复制赋值运算符const的返回参数?

C++ 是否有人发现需要声明复制赋值运算符const的返回参数?,c++,assignment-operator,C++,Assignment Operator,副本分配操作员具有通常的签名: my_class & operator = (my_class const & rhs); 以下签名是否有实际用途 my_class const & operator = (my_class const & rhs); 您只能定义一个或另一个,但不能同时定义两者。是的,它应该是const。否则,客户端可以执行以下操作: class MyClass { public: MyClass & ope

副本分配操作员具有通常的签名:

    my_class & operator = (my_class const & rhs);
以下签名是否有实际用途

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

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

是的,它应该是
const
。否则,客户端可以执行以下操作:

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

void Foo() {
    MyClass a, b, c;
    (a = b) = c; //Yikes!
}

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

< P>有效C++解释这将打破与内置类型的C++的兼容性。 您可以使用纯
int
s执行此操作:

(x = y) = z;
所以他认为,不管这看起来多么愚蠢,一个人也应该能够对自己的类型做同样的事情

这个例子在第二版中有,但在第三版中没有了。然而,第3版第10项中的这句话仍然说明了同样的问题:

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


不要那样做。它阻止客户端编写以下内容:

(a = b).non_const_method();
而不是较长的形式:

a = b;
a.non_const_method();

虽然您可能不喜欢速记风格,但实际上还是由库的用户决定如何编写代码。

这是一个反映以下内容的答案:

返回
常量&
仍将允许分配链接:

a = b = c;
但将禁止一些更不寻常的用途:

(a = b) = c;
请注意,这使得赋值运算符的语义与C中的类似,其中
=
运算符返回的值不是左值。在C++中,标准改变了它,因此<代码> = /COD>操作符返回左操作数的类型,因此结果是一个LValk。但是,尽管这使得编译器可以接受

(a = b) = c;
即使对于内置,结果也是内置的未定义行为,因为
a
被修改两次,没有插入序列点。对于具有
运算符=()
的非内置函数,可以避免该问题,因为
运算符=()
函数调用用作序列点

我认为返回一个
常量&
没有问题,除非您希望特别允许左值语义(并设计类以确保它能够合理地使用这些语义)。如果您是用户,希望对
操作符=()
的结果做一些不寻常的事情,我更希望类不允许它,而不是希望它是偶然而不是设计的

还有。请注意,虽然你说:

您只能定义其中一个,但不能同时定义两个

这是因为C++中的函数签名没有考虑返回值类型。但是,您可以有多个

运算符=()
赋值运算符,它们接受不同的参数并返回与参数类型相应的不同类型:

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

我不完全确定这会给你带来什么。在这两种情况下,分配给的对象(可能是返回的引用)都是非常量的,因此没有逻辑理由返回
常量&
,因为
=
的右侧是
常量
。但也许我遗漏了什么…

为什么每个人都在纠缠
(a=b)=c
?那是偶然写的吗

分配结果的改变可能有一些不可预见的效用。你不只是对那些看起来很有趣的虚构的例子制定武断的规则。从语义上讲,没有理由将其设置为
const
,因此不要将其声明为
const
,以免产生词汇副作用

下面是一个稍微合理的代码示例,它因
const&
赋值而中断:

my_class &ref = a = b;

将副本分配的返回类型作为非常量引用的主要原因是,它是标准中“可分配”的要求


如果将返回类型设为a
const
引用,则您的类将不满足在任何标准库容器中使用的要求。

Hmm。。。。我认为您应该始终使用常量引用声明
运算符*
,以避免
(a*b)=c
,这在内置类型中是非法的。@BillyONeal-使用
运算符*
时,您应该返回一个对象,而不是引用。我很困惑……这很正常。“不,它不应该是常量,因为它破坏了以下代码:。。。(a=b)=c;//哎呀!“:”)但是您违反了所有内置类型和类型设置的约定,如
vector
string
,等等。除非您有真正的原因,否则只需“做INT所做的事情”“。我认为Scott Meyers创造了这个短语。此外,隐式声明的运算符=返回
T&
,因此如果您是结果运算符,则必须始终提供您自己的运算符=。我认为这不值得。写
(a=b)=c
意味着两件事之一-要么
操作符=
有一个异常的post条件,这意味着代码与
a=c
的结果不同,要么第一个赋值是多余的。假设一个“normal”操作符=,我看不出有任何理由支持它。我也看不出有任何理由特意去阻止它。在某些情况下,const-safety会使编写错误代码变得更加困难,但我不认为这是其中之一。所以我认为这是没有理由的。实际上,图书馆也应该阻止用户做图书馆不准备处理的事情。@MichaelBurr-同意,但这不是问题所在。以上只是
a=b的简写符号;a、 非常量方法()@R塞缪尔·克拉奇科:我想你是对的。。。这就是说,我对
操作符=()
使用了一个非常量&return,但是如果我有一点担心这样一个结果可能会被危险地使用,那么我会使用一个类返回一个
常量&
,让用户生活在无法链接操作符的一些方法调用的不便中。这可能有点懒惰
my_class &ref = a = b;