关于完美转发中forward的作用的一点理解

文章讨论了C++中的值类型,包括左值、右值、泛左值和纯右值。它解释了在函数重载选择时如何根据值类型选择合适的函数。此外,文章重点介绍了转发引用(forwardingreference)以及在模板中的作用,特别是`std::forward`如何用于在函数内部正确传递右值引用,解决右值引用作为左值引用导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先先描述一下C++中各种类型的值(以下无特殊说明“类型”皆按如下分法)各种值的类型
lvalue(left value)左值:有标识符,且不能被回收
rvalue(right value)右值:有无标识符皆可,可以被回收
glvalue(generalized left value)泛左值:有标识符,可不可被回收皆可
prvalue(pure right value)纯右值:没有标识符,且可以被回收
xvalue - X值:有标识符,且可以被回收
(还有一些特殊的类型,不过对理解forward帮助不大)

当存在fn(X &); fn(X &&);fn(const X&);几种函数定义时,编译器会根据传入值所属的类型传给对应的函数执行:

  1. 左值(非const)优先找fn(X &),若没有找到,则再寻找fn(const X&),若还没有则报错
  2. 右值类似,优先找fn(X &&),其次fn(const X&)
  3. const左值则只能找fn(const X&)
struct X {};

// overloads
void fn(X &) { std::cout<< "X &\n"; }
void fn(const X &) { std::cout<< "const X &\n"; }
void fn(X &&) { std::cout<< "X &&\n"; }

int main()
{
  X a;
  fn(a);
  // lvalue selects fn(X &)
  // fallbacks on fn(const X &)

  const X b;
  fn(b);
  // const lvalue requires fn(const X &)

  fn(X());
  // rvalue selects fn(X &&)
  // and then on fn(const X &)
}

还存在其他的情况没有完全列出,总之编译器会根据值的类型根据参数值类型按一定规则寻找相应的函数执行

到了模板这里也有类似的情况:

template<typename T>
void foo(T &&); // forwarding reference here
// T is a template parameter for foo

如果这样定义一个模板,根据传入的参数的类型不同,会调用不同的模板实例进行计算,如传入左值则调用foo(T&);传入右值则调用foo(T&&);

而forward主要解决了这样的一个问题:
右值引用作为一种引用,也是一个左值
如果一个函数接受的是T&&这种参数,在该函数体内如果希望用接收到的这个右值引用参数去调用另一个需要右值引用参数的函数是调用不到的,比如:

void reference(int& v) {
    std::cout <<"lvalue" << std::endl;
}
void reference(int&& v) {
    std::cout <<"rvalue" << std::endl;
}
template <typename T>
void pass(T&& v) {
    reference(v);
}
int main() {
    std::cout <<"rvalue pass:";
    pass(1);

    std::cout <<"lvalue pass:";
    int p = 1;
    pass(p);

    return 0;
}

输出为:

rvalue pass:lvalue
lvalue pass:lvalue

在pass(1)的情况下,pass(T&& v)被实例化为pass(int&& v),在pass函数内用这个右值引用(类型为左值)只能调用到reference(int& v),右值引用本身是一个左值

修改代码为:

template <typename T>
void pass(T&& v) {
    reference(std::forward<T>(v));
}

用forward()就能将右值引用(一个左值)转换为右值(xvalue)

forward能够将右值引用和左值引用(均为lvalue)区分出来(利用引用折叠的机制),然后相应地调用static_cast<T&>()转换为lvalue,或static_cast<T&&>()转换为rvalue

参考文章:C++ std::move and std::forward

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值