1.左值和右值
i = i + 1;
所以一个左值可能同时具有做左值和右值的属性,但是不可能是同时是左值或者右值,只能说具有这种属性
2.左值引用和右值引用
左值引用
const & a = 1;
等价于
int b = 1; //可以把b看作一个临时变量
const &c = b;
右值引用是&&,一般用在即将销毁的/临时对象上
例如int && a = 3;
----左值和右值表达式
++i是左值表达式
i++是右值表达式
----右值绑定
所有的变量都要堪称左值,因为他们是有地址的,而且用右值绑定也绑定不上
任何函数里面的形参都是左值,就算是void f(int &&w)这种写法,这里形参w的类型是右值引用(需要绑定到右值),但w本身是左值
临时对象都是右值
----为什么要用右值
为啥用右值呢,它是C++11新加的,可以把它看作一个新的数据类型,主要目的是为了提高效率,怎么实现呢,就是把复制对象变成移动对象,比如之前对象A给对象B的话,是先给B开内存,然后再把A的每个成员赋值给B,这种非常慢,而移动对象是把A的内存块直接给B,然后A去释放,就这样就完事了,之前复制对象的话,有拷贝构造函数,拷贝复制运算符,而移动对象有,移动构造函数和移动复制运算符,只不过前面两个是&,后面两个是&&
3.std::move函数
因为move太容易重名了,所以使用时候都带上std::move,不管写没写using namspace std;
string def = std::move(st)是触发了string类的移动构造函数,而对于string && def = std::move(st)并没有触发string类的移动构造函数
4.隐式类型转换
CTempValue sum; sum = 1000; 和 CTempValue sum = 100 后者比前者少调用了一次构造函数,一次拷贝赋值运算符,少调用了一次析构函数 后者的=不是赋值运算符,而是“定义时初始化”的概念,这个代码的过程是,在这里定义了sum对象-- --系统为sum对象创建了预留空间,然后用1000调用构造函数来构造临时对象,但是这个构造是在预留空间里进行的,所以并没有真正的产生临时对象
C++只会为const引用(const string& aaa)产生临时对象,而不会为非const引用string& aaa产生临时对象
void test(const string& aaa)
临时对象就是一种右值