C++完美转发
简要来说完美转发就是函数接收参数时保持参数原本的值类别左值还是右值原封不动地传给另一个函数。void process(int x) { cout 左值\n; } void process(int x) { cout 右值\n; } templatetypename T void wrapper(T arg) { process(arg); // 问题arg 在函数内部永远是左值 } int main() { int x 10; wrapper(x); // 期望调用 process(int) → 左值 wrapper(10); // 期望调用 process(int) → 右值 }结果两次都输出左值。因为arg在wrapper内部是个有名字的变量不管它初始化时绑定的对象是什么它本身永远是左值。右值属性丢了解决方案万能引用std::forward1.万能引用templatetypename T void wrapper(T arg) { // 注意T 是万能引用不是右值引用 process(std::forward(arg)); }关键T在模板推导中是万能引用能同时接受左值和右值传左值int x→T推导为intT变成int → 引用折叠为int传右值10→T推导为intT变成int2. std::forward 的作用std::forward是个条件转换templatetypename T T forward(remove_reference_t arg) { return static_castT(arg); }核心逻辑如果T是左值引用int→static_castint(arg)→ 返回左值引用如果T是非引用int→static_castint(arg)→ 返回右值引用它把arg还原成传入时的值类别。引用折叠规则底层机制类型组合折叠结果T TT TT TT T常见误区误区 1T一定是右值引用错。只有两种情况是右值引用非模板上下文void f(int x)明确指定类型fint(...)模板推导中的T是万能引用。误区 2转发需要std::move错std::move强制转右值会破坏左值语义。完美转发必须用std::forward。误区 3所有参数都要转发只有当你需要保持原样传递时才用。如果函数内部要多次使用参数不要转发否则可能触发移动导致资源被掏空。完整例子#include iostream #include utility using namespace std; void process(int x) { cout 左值引用\n; } void process(int x) { cout 右值引用\n; } templatetypename T void wrapper(T arg) { process(forward(arg)); // 完美转发 } int main() { int x 10; wrapper(x); // 输出左值引用 wrapper(10); // 输出右值引用 wrapper(move(x)); // 输出右值引用显式转右值 }