为何std::forward<T>无法完美转发T&&参数?兼谈decay_copy的拷贝问题
完美转发与auto(x)的问题解析
一、为什么return std::forward<T>无法完美转发T&&类型的参数?
先看给定的decay_copy实现:
template<class T> constexpr decay_t<T> decay_copy(T&& v) noexcept( is_nothrow_convertible_v<T, decay_t<T>>) { return std::forward<T>(v); }
问题的核心不在std::forward<T>本身,而在于返回值类型decay_t<T>:
decay_t<T>是对T做类型退化后的结果:数组转指针、引用被移除、cv限定符丢弃,最终得到的是一个非引用的具体类型。- 当你
return std::forward<T>(v)时,不管std::forward转出的是左值还是右值,最终都要被转换为decay_t<T>类型的返回值。哪怕原参数是prvalue(比如x.front()返回临时对象),std::forward<T>(v)生成的prvalue也会被用来拷贝初始化返回值对象——标准不强制返回值优化的情况下,这个拷贝操作无法避免。
简单说:返回值类型固定为退化后的非引用类型,把std::forward传递的值类别信息给截断了,自然无法实现完美转发。
二、std::forward<T>是否应当完美转发万能/转发引用声明的输入参数?
答案是肯定的——std::forward的设计初衷就是完美转发万能引用参数:
- 当万能引用
T&&推导为左值引用(传入左值),std::forward<T>会将参数转换为左值; - 当推导为右值引用(传入右值),
std::forward<T>会将参数转换为右值。
回到decay_copy的问题:std::forward已经正确完成了转发工作,但返回值类型decay_t<T>是个非引用类型,导致转发后的结果必须被拷贝到返回值中,无法保留原参数的值类别。这也是C++引入auto(x)的原因:auto(x)能实现带退化的完美转发——既对对象做类型退化,又保留原有的值类别,避免不必要的拷贝操作。
内容的提问来源于stack exchange,提问作者sandthorn
相关产品推荐
相关产品推荐

