1.右值引用:
右值引用其实就是对一个临时右值表达式的引用,表达式中不能出现任何变量。
例如:int &&a=1;和const int &a=1; 他们两的操作时完全等价的。而且右值引用的实质是在数据区开辟一个无名变量然后进行绑定而已。
形如const A& a = GetA()的是常量左值引用,是一个“万能”的引用类型,可以接受左值、右值、常量左值和常量右值。需要注意的是普通的左值引用不能接受右值。
右值引用的三个特点:
通过右值引用的声明,右值又“重获新生”,其生命周期与右值引用类型变量的生命周期一样长,只要该变量还活着,该右值临时量将会一直存活下去。
右值引用独立于左值和右值。意思是右值引用类型的变量可能是左值也可能是右值。
T&& t在发生自动类型推断的时候,它是未定的引用类型(universal references),如果被一个左值初始化,它就是一个左值;如果它被一个右值初始化,它就是一个右值,它是左值还是右值取决于它的初始化。
完美转发:在函数模板中,完全依照模板的参数的类型(即保持参数的左值、右值特征),将参数传递给函数模板中调用的另外一个函数。C++11中的std::forward正是做这个事情的,他会按照参数的实际类型进行转发。
这里再提一下引用折叠,正是因为引入了右值引用,所以可能存在左值引用与右值引用和右值引用与右值引用的折叠,C++11确定了引用折叠的规则,规则是这样的:
- 所有的右值引用叠加到右值引用上仍然还是一个右值引用;
- 所有的其他引用类型之间的叠加都将变成左值引用。
通过4行代码我们知道了什么是右值和右值引用,以及右值引用的一些特点,利用这些特点我们才方便实现移动语义和完美转发。C++11正是通过引入右值引用来优化性能,具体来说是通过移动语义来避免无谓拷贝的问题,通过move语义来将临时生成的左值中的资源无代价的转移到另外一个对象中去,通过完美转发来解决不能按照参数实际类型来转发的问题(同时,完美转发获得的一个好处是可以实现移动语义)。
2.数据封装不仅仅是简单地将数据代码连接在一起。更包括class那样的将数据和操作绑在一起为用户提供服务地功能。
3.宏定义里面的#:
#define DECLARE(name, type) type name##_##type##_type
DECLARE(pop,int)
我们是从左到右进行替换,首先遇到type,检测到有宏定义传入则转化为int,然后又向右查看,检测到一个name转化为pop,检测到##我们等待下一个字符串并即将连在一起,发现是一个横杠,于是连在一起成为int pop_以此类推就能得到正确地替换字符串。