C++ 完美转发是泛型编程里一个关键特性,用来在模板函数中保持参数的“原始值类别”(lvalue/rvalue)和属性(const、引用)。
背景
在模板编程中,函数参数往往需要被“原封不动”地传递到另一个函数。例如:
- 如果传入的是左值,就要继续作为左值传给目标函数;
- 如果传入的是右值,就要继续作为右值传给目标函数。
直接写模板会遇到一个问题:参数类型容易丢失引用或值类别,导致额外拷贝或无法调用合适的重载。如下所示:
template<typename T>
void wrapper(T arg) {process(arg); // 无论传入左值还是右值,arg都是左值
}
基本机制
完美转发主要依赖于两个机制:
1. 转发引用
当 T
是模版类型参数时,T&&
可以绑定到任何类型的参数(左值或者右值)。它遵循引用折叠规则:
- 当传入左值时,
T
推导为T&
,于是T&&
折叠为T& &&
->T&
; - 当传入右值时,
T
推导为T&&
,于是T&&
折叠为T&& &&
->T&&
。
2. forward
std::forward<T>(arg)
会根据 T
的类型,决定是转为左值引用还是右值引用,从而保持原始的值类别。
示例:工厂函数
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
完美转发主要用于在泛型编程和库设计中提升灵活性和效率,减少拷贝和临时对象。