C++引用折叠
C++引用折叠详解
引用折叠(Reference Collapsing)是C++模板和类型推导中的一个重要规则,它决定了当引用被应用于引用时会发生什么情况。
引用折叠规则
在C++中,引用折叠遵循以下规则:
T& &
→T&
T& &&
→T&
T&& &
→T&
T&& &&
→T&&
简单来说,只要其中有一个是左值引用(&
),结果就是左值引用;只有当两个都是右值引用(&&
)时,结果才是右值引用。
为什么需要引用折叠
引用折叠主要出现在以下场景:
- 模板类型推导中
typedef
或using
别名中decltype
表达式中
示例
示例1:模板函数中的引用折叠
template<typename T>
void foo(T&& param) { // 这里是万能引用(universal reference)// 根据传入参数类型,T会被推导为不同形式
}int main() {int x = 10;const int cx = 20;foo(x); // T被推导为int&,参数类型为int& && → int&foo(cx); // T被推导为const int&,参数类型为const int& && → const int&foo(30); // T被推导为int,参数类型为int&&
}
示例2:类型别名中的引用折叠
template<typename T>
struct Widget {typedef T&& RvalueRef;
};int main() {Widget<int&>::RvalueRef r1; // int& && → int&Widget<int&&>::RvalueRef r2; // int&& && → int&&
}
示例3:auto和decltype中的引用折叠
int main() {int x = 10;auto&& y = x; // auto被推导为int&,y的类型是int& && → int&auto&& z = 42; // auto被推导为int,z的类型是int&&decltype(x)&& a = 30; // decltype(x)是int,a的类型是int&&decltype((x))&& b = x; // decltype((x))是int&,b的类型是int& && → int&
}
示例4:完美转发中的引用折叠
template<typename T>
void wrapper(T&& arg) {// 使用std::forward保持值的类别some_function(std::forward<T>(arg));
}void some_function(int& x) { std::cout << "lvalue\n"; }
void some_function(int&& x) { std::cout << "rvalue\n"; }int main() {int a = 10;wrapper(a); // 输出"lvalue"wrapper(20); // 输出"rvalue"const int b = 30;wrapper(b); // 调用some_function(const int&)
}
总结
引用折叠是理解C++现代模板编程的关键概念之一,特别是在处理万能引用和完美转发时。记住引用折叠的四个规则,可以帮助你更好地理解模板类型推导和引用行为。