c++中为啥赋值运算符重载返回类型是引用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++中为啥赋值运算符重载返回类型是引用相关的知识,希望对你有一定的参考价值。
一、c/c++赋值运算符的本意为“返回左值的引用”(左值:赋值号左面的变量而非其值)例:
int
a,
b
=
3,
c
=
2;
(a
=
b)
=
c;
cout<<a<<endl;
对于a
=
b(a,b均为对象时),若不返回左值的引用,将会生成临时对象。如果不处理a
=
b
=
c这样的表达式,也会正常(只是会调用拷贝构造函数和析构函数处理临时对象)。
二、为了进行连续赋值,即
x
=
y
=
z
1、赋值返回引用
x
=
y
=
z
先执行y
=
z,返回y的引用,执行x
=
y
2、赋值不返回引用
x
=
y
=
z
先执行y
=
z,返回用y初始化的临时对象(注意临时对象都是常对象),再执行x
=
y的临时对象(要求operator=(const
X&)
),返回用x初始化的临时对象(此处要求拷贝构造函数必须为X(const
X&)
)。
所以也并非必须返回引用,返回引用的好处既可以于赋值的原始语义已知,又可避免拷贝构造函数和析构函数的调用。 参考技术A 因为赋值操作会改变左值,而
+
之类的运算符不会改变操作数,所以说赋值运算符重载要返回引用以用于类似
(a=b)=c
这样的再次对a=b进行写操作的表达式。+
返回一个临时对象是合情合理的
,你若返回引用大多数情况下也不会出错或导致某个操作数被意外修改,但这就使(a+b)=c这样的表达式可以出现,这就有点不符合约定了,当然,你也可以让
+
返回一个常引用。 参考技术B 重载运算符时,首先要考虑使重载后的运算符符合c++默认语法的语义。
就赋值号而言,c++中允许这样的用法:
int
a,
b;
b
=
(a
=
1);
注意其中的赋值表达式(a
=
1)是返回变量a(此时其值为1)的。这个返回值就是赋值运算符的返回值。这样一来变量b也可以被赋值为a。
因此,我们自己重载赋值运算符以后,也要返回被赋值的对象,即this。 参考技术C 一、c/c++赋值运算符的本意为“返回左值的引用”(左值:赋值号左面的变量而非其值)
例:
int
a,
b
=
3,
c
=
2;
(a
=
b)
=
c;
cout<<a<<endl;
对于a
=
b(a,b均为对象时),若不返回左值的引用,将会生成临时对象。如果不处理a
=
b
=
c这样的表达式,也会正常(只是会调用拷贝构造函数和析构函数处理临时对象)。
二、为了进行连续赋值,即
x
=
y
=
z
1、赋值返回引用
x
=
y
=
z
先执行y
=
z,返回y的引用,执行x
=
y
2、赋值不返回引用
x
=
y
=
z
先执行y
=
z,返回用y初始化的临时对象(注意临时对象都是常对象),再执行x
=
y的临时对象(要求operator=(const
X&)
),返回用x初始化的临时对象(此处要求拷贝构造函数必须为X(const
X&)
)。
所以也并非必须返回引用,返回引用的好处既可以于赋值的原始语义已知,又可避免拷贝构造函数和析构函数的调用。 参考技术D 不要一定非要是引用的,用引用是为了可以写A+B+C这样的连续表达式
返回的不是引用或指针则只能用于赋值
为啥我们在赋值运算符重载中使用引用返回而不是在加减运算中?
【中文标题】为啥我们在赋值运算符重载中使用引用返回而不是在加减运算中?【英文标题】:Why we use reference return in assignment operator overloading and not at plus-minus ops?为什么我们在赋值运算符重载中使用引用返回而不是在加减运算中? 【发布时间】:2014-02-24 11:02:54 【问题描述】:正如我在书籍和网络中所读到的,在 C++ 中,我们可以使用这些原型重载“加号”或“减号”运算符(作为 class Money
的成员函数):
const Money operator +(const Money& m2) const;
const Money operator -(const Money& m2) const;
对于赋值运算符:
const Money& operator =(const Money& m2);
为什么在赋值运算符重载中而不是在加号和减号运算符中使用对 Money 对象的引用作为返回值?
【问题讨论】:
如果您在+
或-
二进制操作中返回一个引用,它应该引用什么?返回引用是没有意义的。该操作必须创建一个新对象。
你不希望能够编码 a + b = c;
【参考方案1】:
从赋值返回引用允许链接:
a = b = c; // shorter than the equivalent "b = c; a = b;"
(如果运算符返回新值的副本,这也可以(在大多数情况下),但通常效率较低。)
我们不能从算术运算中返回引用,因为它们会产生一个新值。返回新值的唯一(明智的)方法是按值返回。
如您的示例那样,返回一个常量值会阻止移动语义,所以不要这样做。
【讨论】:
为什么?不,赋值链接与赋值运算符返回的内容有关。在任何版本中都可以使用赋值链接(如您的示例)。返回 const 引用将防止对 lhs 进行多次修改,如 '(a = b) = c',但这是另一回事。 换句话说,需要从赋值返回的非常量引用的情况相当深奥,通常属于“糟糕的编程实践”类别,因此人们甚至可能会看到一些明确推荐的来源 从赋值返回 const 引用。 @AndreyT:你说得对,我自己都搞糊涂了。 (当然,你必须返回一些东西以允许链接;但它可以是一个值或常量引用。)【参考方案2】:因为operator+
和operator-
不作用于this 对象,而是返回一个新对象,该对象是该对象与另一个对象的总和(或减法)。
operator=
是不同的,因为它实际上是分配一些东西给这个对象。
operator+=
和 operator-=
将作用于该对象,并且更接近于 operator=
。
【讨论】:
【参考方案3】:考虑一下您的要求。您可能希望表达式a + b
返回对a 或b 之一的引用,这将具有表达式的结果。因此,您可以将 a 或 b 中的一个修改为 a 和 b 的总和。因此,您可能希望将运算符 (+) 的语义重新定义为与运算符 (+=) 相同。就像@manuell 说的那样,您将因此允许(a + b) = c
。 += 和 -= 已经提供了您建议的语义。
【讨论】:
【参考方案4】:我认为如果你在重载的赋值运算符中按值返回就可以了,那是因为赋值运算符的关联性。考虑一下:
int a = b =c = 3 ;
这里的关联性如下: (a=(b=(c=3)))
但考虑iostream操作 cout
这里的关联性如下: (((cout
可以看到先打印x,所以如果在
还有一点,如果你按值返回,复制构造函数将被调用。 (这不是通过引用返回的情况)
【讨论】:
【参考方案5】:我猜下面显示的链接有更好的解释 return value of operator overloading in C++
【讨论】:
以上是关于c++中为啥赋值运算符重载返回类型是引用的主要内容,如果未能解决你的问题,请参考以下文章