这是来自'03或'04的C ++筛选测试。
以下哪一项声明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)。现在,这是怎么回事?它是如何工作的?什么叫什么? parens强制临时创建? const如何参与混合?
答案 0 :(得分:5)
作业是右关联的,所以
a=b=c
相当于
a=(b=c)
通过使operator=
返回一个const值,您不能再分配给它,所以
(a=b)=c
不起作用,但这不会影响a=(b=c)
,因为您正在阅读作业的结果而不是写作。
答案 1 :(得分:4)
将赋值重写为函数调用而不是运算符可能会有所帮助(正如其他人明确说明的那样,没有任何(),赋值从右到左):
Line 2: a.operator=(b.operator=(c));
Line 3: (a.operator=(b)).operator=(c);
这使得更清楚的是,在第3行,您尝试获取a=b
的结果并将c
分配给该operator=
。但是在第3种情况下,operator=
的输出是一个const对象,因此不允许这样做(因为// 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.
来消除任何与运算符相关的混淆:
{{1}}
答案 2 :(得分:2)
赋值是右关联的,因此第2行等同于:
a = (b = c);
这意味着必须有从MyClass
到MyClass
的作业,并且返回类型可以分配给MyClass
。
第二个和第三个选项显然填满了这些要求(就像让编译器生成默认赋值运算符一样)。
第三行虽然要求MyClass
可以分配给MyClass
到MyClass
的分配的返回值,只有第二个选项允许,虽然语义不好。
结合它,问题要求选项3。
赋值运算符应该将引用返回到左侧对象,而不使用任何cv限定符,以进行正确的链接。
阅读本文,了解运算符重载的详细信息和背景:Operator overloading
答案 3 :(得分:1)
这两行都有2个作业。当分成多行语句时,它们看起来像这样:
Line 2: a=b
b=c
Line 3: a=b
a=c
等于运算符返回左侧。由于选择3返回一个const MyClass,当尝试重新分配一个常量变量时,第3行将发生错误。