C++;常量重载赋值运算符机制 这是来自于03或04的C++筛选试验。
以下哪项声明MyClass的赋值运算符,以便第3行的代码生成编译错误,而第2行的代码不生成编译错误 考虑以下代码片段: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=(
(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);一个关于常量正确性和无用常量返回值(没有引用)的愚蠢问题,我非常同意,但我不同意