条款24:区分万能引用与右值引用
条款24:区分万能引用与右值引用
核心结论
| 判断条件 | 结果 |
|---|---|
是 T&&,并且发生类型推导 |
万能引用(universal reference) |
是 T&&,但没有类型推导 |
右值引用(rvalue reference) |
const T&& / vector<T>&& 等非标准形式 |
右值引用(rvalue reference) |
auto&&,发生类型推导 |
万能引用(universal reference) |
万能引用(Universal Reference)
也称 转发引用(Forwarding Reference)
条件
- 声明形式必须是
T&&(或auto&&) - 类型
T(或auto)必须通过 类型推导 得出
特性
- 可绑定左值、右值
- 可绑定
const、volatile或任意组合 - 初始化值决定实际类型(引用折叠规则起作用):
- 初始化为左值 → 左值引用(
T&) - 初始化为右值 → 右值引用(
T&&)
- 初始化为左值 → 左值引用(
示例
template<typename T>
void f(T&& param); // T 通过调用 f 时推导出来 → 万能引用
auto&& val = expr; // 万能引用(C++11 起)
// C++14 lambda 中的万能引用
auto lambda = [](auto&& x) { /* ... */ };
右值引用(Rvalue Reference)
条件
T&&,但类型没有推导,而是显式指定- 或者形式不是
T&&(如const T&&,vector<T>&&)
示例
void f(Widget&& param); // 右值引用
Widget&& var = Widget(); // 右值引用
template<typename T>
void f(const T&& param); // 右值引用(const 修饰失去万能性)
template<typename T>
void f(std::vector<T>&& param); // 右值引用(不是 T&&)
容易混淆的场景
错误地以为是万能引用:
template<typename T>
void f(const T&& param); // 右值引用(const 破坏了万能性)
template<typename T>
void f(std::vector<T>&& param); // 右值引用(不是 T&&)
template<typename T>
class MyVec {
void push_back(T&& val); // T 已经由类模板实例化时指定 → 没有推导
};
真正的万能引用:
template<typename T>
void f(T&& param); // ✅ 万能引用
template<typename... Args>
void emplace_back(Args&&... args); // ✅ 万能引用参数包
auto&& val = getValue(); // ✅ auto&& 是万能引用
应用意义
- 完美转发:
- 只有万能引用能使用
std::forward实现完美转发
- 只有万能引用能使用
- 接口设计:
- 右值引用用于移动语义(只接收右值)
- 万能引用用于接收任意类型并完美转发
- 提高阅读/维护能力:
- 分辨 T&& 是哪种引用,避免误用

浙公网安备 33010602011771号