- 之前比较难理解的主要就是右值和左值,右值引用和左值引用。
- 左值与右值的根本区别在于是否允许取址运算符(&)获得对应的内存地址。左值和右值比较简单的理解,也就是顾名思义,在赋值表达式中,用在=号左侧的是左值,是可以被赋值的,多半是一个声明过的变量,但是用在等号右侧的不一定就是右值,因为左值也可以出现在=号右侧,通常来讲我们说的右值一般是函数返回值(使用运算符的表达式返回结果同理),它是一个临时对象,或者是一个字面量比如10,“bob”这种。接下来是左值引用和右值引用,左值引用没什么好说的,一般就是变量的引用这个平时用的很多。而右值引用这个是c++11新加的东西,这个就值得研究一下了。
- 右值引用主要意义在于实现移动语义和完美转发。
std::move可以把左值引用转为右值引用,这个东西主要作用在于避免一些临时对象的多余复制。比如当临时对象有移动构造函数时,在使用stl容器的时候就可以在pushback的时候使用std::move省去一次拷贝构造和析构。
std::forward这个的主要作用在于他不会把右值转换为左值,避免了内存分配。
从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。
右值引用可以直接指向右值,也可以通过std::move指向左值;而左值引用只能指向左值(const左值引用也能指向右值)。
作为函数形参时(int &&ref为右值引用, int &ref为左值引用),右值引用更灵活。虽然const左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。
- tips:
左值引用不能指向右值,但是const左值引用可以。比如 const int &ref_a = 5; 是可以编译通过的,因为const左值引用无法修改指向的值,所以可以指向右值。c++标准库中的vector push_back void push_back (const value_type& val); 就是这样实现的,如果没有这个const, vector.push_back(1),这种代码是无法编译通过的。
编译器会默认在用户自定义的class和struct中生成移动语义函数,但前提是用户没有主动定义该类的拷贝构造等函数
参考文献
未完待续