赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型.也就是说,如果i是int,表达式i=x的类型是int &
为什么i=x不是int而非要绕个弯是int &?
“赋值会产生引用”的含义是,赋值表达式的返回值是引用类型。这里包含两个问题,
-
首先,赋值表达式为什么要有返回值呢?为了支持链式的复制表达式!
cpp
int a,b; a = b = 1; // 等号运算符是右结合的,相当于: a = (b = 1);
其实是把
b=1
的返回值赋给了a
,所以赋值表达式要有返回值。 -
为什么不反回值,而是返回引用呢?为了效率!而且通常返回常量引用。比如你的赋值变量不是基本数据类型,而是对象时:
cpp
Obj a, b, c; a = b = c;
如果
b=c
返回的是值,则需要在=
运算结束后,调用拷贝构造函数将结果复制为返回值(因为函数结束后栈空间是要被销毁的,而局部变量存储在栈空间中)。如果返回引用,则不需要调用复制返回值,直接将引用原有的变量。
举个例子吧,比如Obj类的赋值运算符是这样重载的:
cpp
class Obj{ int x; public: Obj& operator=(const Obj& rhs){ x = rhs.x; return *this; } };
那么在b = c
结束后,返回的*this
是b
的引用。如果你写的是:
cpp
Obj operator=(...){ ... return *this; }
则在return *this
后,*this
会被拷贝为一个新的对象作为返回值存起来。多一次拷贝构造函数的调用过程。
赋值运算符的一般重载方法,以及为何要返回*this
,可以参考这篇文章:
http://harttle.github.io/2015/07/28/effective-cpp-10.html
关于拷贝构造函数、赋值运算符的调用时机以及重载方法,可以参考:
http://harttle.github.io/2015/07/23/effective-cpp-5.html