C++;常量重载赋值运算符机制 这是来自于03或04的C++筛选试验。

C++;常量重载赋值运算符机制 这是来自于03或04的C++筛选试验。,c++,operator-overloading,constants,assignment-operator,c++03,C++,Operator Overloading,Constants,Assignment Operator,C++03,以下哪项声明MyClass的赋值运算符,以便第3行的代码生成编译错误,而第2行的代码不生成编译错误 考虑以下代码片段: (Line 1) MyClass a, b, c; (Line 2) a=b=c; (Line 3) (a=b)=c; 1) void operator=( const MyClass& X ); 2) MyClass operator=( const MyClass& X ); 3) const MyClass operator=(

以下哪项声明MyClass的赋值运算符,以便第3行的代码生成编译错误,而第2行的代码不生成编译错误

考虑以下代码片段:

   (Line 1) MyClass a, b, c; 
   (Line 2) a=b=c; 
   (Line 3) (a=b)=c; 

1) void operator=( const MyClass& X );
2) MyClass operator=( const MyClass& X );
3) const MyClass operator=( const MyClass& X );
4) None of the above

正确答案是3)。这是怎么回事?它是如何工作的?什么叫什么?Paren是否强制创建临时文件?const是如何参与混合的?

赋值是右关联的,所以

a=b=c
相当于

a=(b=c)
通过使
operator=
返回常量值,您将无法再为其赋值,因此

(a=b)=c

不起作用,但这不会影响
a=(b=c)
,因为您正在读取作业结果,而不是写入作业。

作业是右关联的,因此

a=b=c
相当于

a=(b=c)
通过使
operator=
返回常量值,您将无法再为其赋值,因此

(a=b)=c

不起作用,但这不会影响
a=(b=c)
,因为您正在读取赋值结果,而不是写入。

将赋值重写为函数调用而不是运算符可能会有所帮助(正如其他人明确指出的,没有任何(),赋值从右向左进行):

这使第3行更加清楚,您试图获取
a=b
的结果,并将
c
分配给该结果。但是在案例3中,
operator=
的输出是一个常量对象,因此这是不允许的(因为
operator=
是一个非常量函数)

将每个赋值分解为两个单独的语句可能更为清楚:

// with const MyClass MyClass::operator=( const MyClass& X );

// line 1
MyClass a, b, c; 

//line 2; originally a=b=c
const MyClass d = (b = c);
a = d; // no problem; a is nonconst, and it's ok for d (the parameter to operator=) to be const

//line 3; originally (a=b)=c
const MyClass e = (a = b); // note: the leftmost = here is initialization rather than assignment
e = c; // no good! e is const, and you can't call a nonconst function like operator= on a const object
或者更进一步,只需使用名为
assign
的函数代替
operator=
,就可以消除任何与运算符相关的混淆:

// with const MyClass MyClass::assign( const MyClass& X );

// line 1
MyClass a, b, c; 

//line 2; originally a=b=c
const MyClass d = b.assign(c);
a.assign(d); // ok. assign() is nonconst, but so is a.

//line 3; originally (a=b)=c
const MyClass e = a.assign(b);
e.assign(c); // no good! e is const and assign() is not.

将赋值重写为函数调用而不是运算符可能会有所帮助(正如其他人明确指出的,没有任何(),赋值从右向左进行):

这使第3行更加清楚,您试图获取
a=b
的结果,并将
c
分配给该结果。但是在案例3中,
operator=
的输出是一个常量对象,因此这是不允许的(因为
operator=
是一个非常量函数)

将每个赋值分解为两个单独的语句可能更为清楚:

// with const MyClass MyClass::operator=( const MyClass& X );

// line 1
MyClass a, b, c; 

//line 2; originally a=b=c
const MyClass d = (b = c);
a = d; // no problem; a is nonconst, and it's ok for d (the parameter to operator=) to be const

//line 3; originally (a=b)=c
const MyClass e = (a = b); // note: the leftmost = here is initialization rather than assignment
e = c; // no good! e is const, and you can't call a nonconst function like operator= on a const object
或者更进一步,只需使用名为
assign
的函数代替
operator=
,就可以消除任何与运算符相关的混淆:

// with const MyClass MyClass::assign( const MyClass& X );

// line 1
MyClass a, b, c; 

//line 2; originally a=b=c
const MyClass d = b.assign(c);
a.assign(d); // ok. assign() is nonconst, but so is a.

//line 3; originally (a=b)=c
const MyClass e = a.assign(b);
e.assign(c); // no good! e is const and assign() is not.

两行都有两个作业。当分解成多行状态时,它们看起来如下所示:

Line 2: a=b
        b=c
Line 3: a=b
        a=c

equals运算符返回左侧。由于选项3返回常量MyClass,当尝试重新分配常量变量时,第3行将出现错误。

两行都进行了2次赋值。当分解成多行状态时,它们看起来如下所示:

Line 2: a=b
        b=c
Line 3: a=b
        a=c

equals运算符返回左侧。由于选项3返回常量MyClass,当尝试重新分配常量变量时,第3行将出现错误。

赋值是右关联的,因此第2行相当于:

a = (b = c);
这意味着必须有一个从
MyClass
MyClass
的赋值,返回类型可以赋值给
MyClass

第二个和第三个选项显然满足了这些要求(就像让编译器生成默认赋值运算符一样)

但第三行要求可以将
MyClass
赋值给
MyClass
赋值给
MyClass
的返回值,这只有第二个选项允许,尽管语义不好

结合这一点,问题要求选择3

赋值运算符应返回对左侧对象的引用,不带任何cv限定符,以便进行正确的链接。

有关运算符重载的详细信息和背景信息,请阅读此内容:

赋值是右关联的,因此第2行相当于:

a = (b = c);
这意味着必须有一个从
MyClass
MyClass
的赋值,返回类型可以赋值给
MyClass

第二个和第三个选项显然满足了这些要求(就像让编译器生成默认赋值运算符一样)

但第三行要求可以将
MyClass
赋值给
MyClass
赋值给
MyClass
的返回值,这只有第二个选项允许,尽管语义不好

结合这一点,问题要求选择3

赋值运算符应返回对左侧对象的引用,不带任何cv限定符,以便进行正确的链接。

阅读本文了解运算符重载的详细信息和背景:

一个关于常量正确性和无用常量返回值(没有参考)的愚蠢问题。我非常同意,但我没有进行攻击的基础。11年前,我弄错了,我觉得自己被虐待了,因为我当时觉得自己被“抓住了”,一个琐碎的细节。我今天遇到了它,现在我想知道。这是一种人为的情况,但它确实测试了人们对常量、运算符重载和关联性的理解程度。也就是说,他们最好使用一个在现实世界中编写的代码示例。但也许这就是重点,他们希望你说“正确答案是3,但这是一个愚蠢的问题。”:)对于加分,为什么在C++11中这是一个坏主意?我建议返回引用而不是副本,即2)MyClass&operator=(const MyClass&X);和3)constmyclass&operator=(constmyclass&X);一个关于常量正确性和无用常量返回值(没有引用)的愚蠢问题,我非常同意,但我不同意