061-右值引用
左值与右值
C++ 中值有两个独立的属性:有地址的值(gvalue)和可以被移动的值(rvalue)
有地址 + 不能移动 = 左值(lvalue)
有地址 + 可以移动 = 将亡值(xvalue), 包括: 右值引用类型的返回值,比如
std::move(x)
没有地址 + 可以移动 = 纯右值(prvalue), 包括:
- 字面量,比如
42
- 临时对象,比如
1 + 2
- this 指针
- 字面量,比如
没有地址 + 不能移动, 目前没有用到
总之, 一个值是左值还是右值,取决于它的地址是否可以被获取。大多数时候只需要区分一个值是左值还是右值即可。
右值引用
右值引用是 C++11 引入的一种引用类型,用于表示对右值的引用。右值引用可以绑定到右值,但不能绑定到左值。右值引用通常用于实现移动语义和完美转发。
- 右值引用只能绑定到右值上,比如
int &&
- 左值引用只能绑定到左值上,比如
int &
- const 的左值引用可以绑定到左值或右值上,比如
const int &
移动构造函数和移动赋值运算符
1 | class Widget { |
移动操作和异常安全
- 移动操作一般不分配新资源,因此不会抛出异常
- 如果移动操作不抛异常,必须注明 noexcept
通用引用和引用折叠
通用引用
通用引用是一种既可以绑定到左值,又可以绑定到右值的引用类型,其本质是一个模板参数化的右值
1 | template <typename T> |
引用折叠
引用折叠规则:
左值引用(&)优先级高于右值引用(&&)。
以下是所有的折叠情况:
- T& & → T&
- T& && → T&
- T&& & → T&
- T&& && → T&&
remove_reference
std::remove_reference 是 C++ 标准库中的一个类型特性(type trait),定义在头文件
1 | template <typename T> |
常用场景: 类型推导、模板元编程、完美转发等。
总结
- std::remove_reference 是一个编译期工具,通过模板特化对类型进行处理。
- 它不会在运行时产生临时变量,也不会涉及任何值类别的转换。
- 编译器只会根据类型推导规则替换类型,例如将 int& 转换为 int,最终生成相应的代码。
- 不会去掉 const 和 volatile 修饰符
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Hymns!