每日小结
#c++11(新?)特性之右值引用
#右值
不能放到赋值表达式左侧的值
例如:
- 字面量
1, "Hello", 'c'
- 返回值而非引用的函数调用
foo()
- 运算结果
a + b
右值不能被直接赋值给一个非常引用, 只能先赋给一个变量再取引用
1 | int& ref = 9; // error, “invalid initialization of non-const reference of type int& from an rvalue of type int” |
上述特性在泛型函数重载时会带来一些问题, 这导致我们不得不对有无const两种情况分别重载
1 | template <typename T, typename A1> |
#右值引用
顾名思义, 就是对右值的引用
#增加右值引用的好处
增加了右值引用之后, 我们具备了识别和重载右值的能力
#进一步消除不必要的复制
在c++11之前, 临时变量的创建一直是难以处理的问题. 有时这些临时变量可以被编译器优化(例如返回值优化), 但是这并不总是可行的, 通常这会导致高昂的对象复制成本.
考虑下面的代码, 理论上这里最多可能发生两次复制操作:
返回临时变量
vector赋值
其中, 第一次的复制操作可能会被编译器优化掉(RVO), 然而第二次复制是不可避免的
当然我们可以通过其他方法来避免这次复制, 比如通过指针或者传递一个已经填充好的vector
1 |
|
有了右值引用之后, 我们可以就可以对右值进行特殊化处理, 从而避免多余的复制(移动构造函数和=运算符重载), 例如
1 | // copy |
#移动语义的引入
可以显式指定某个资源被移交给另一个函数, 自己不再需要
1 | Resource resource; |
对于有些不能被复制的资源(如std::unique_ptr
, std::thread
等等), 这是很有用的
1 | std::string s; |
#模板的完美转发
(TODO)
#实现
move
函数: 提醒编译器重载时选择移动构造函数
利用移动交换两个变量:
1 | void move_swap(Res &a, Res &b) |
#RVO和NRVO
返回值优化(Return value optimization,缩写为RVO)是C++的一项编译优化技术。即删除保持函数返回值的临时对象。这可能会省略两次复制构造函数,即使复制构造函数有副作用。