完美转发

解决的问题

当一个函数接收右值参数后,再将此参数传给另外一个函数时本是右值的参数变成左值,造成无法利用针对右值的性能优化的问题。

解决方法

在模板中用std::forward(x)来实现“完美转发”,即原来的左值参数仍为左值,原来的右值参数保持为右值。

实现方法

根据模板中引用折叠的规则:

T& & –> T&
T&& & –> T&
T& && –>T&
T&& && –> T&&

std::forward() 用static_cast 来实现完美转发。

_NODISCARD constexpr _Ty&& forward(
    remove_reference_t<_Ty>& _Arg) noexcept { // forward an lvalue as either an lvalue or an rvalue
    return static_cast<_Ty&&>(_Arg);
}

虽然不能隐式的将一个左值转换为右值引用,但是可以通过static_cast显示地将一个左值转换为一个右值。

如何理解 std::forward

程序告诉编译器,这个非引用变量我不再用了,可以作为右值传给调用堆栈的下一级,编译器可以依赖此声明放心去做优化(比如调用移动构造器而非拷贝构造器)了。

一般用于将传入的参数转发给下一级函数,自己实际上不会做任何处理,因此叫“完美转发”。传进来的参数可能有三种情况:

  1. 值传递 Type arg
  2. 引用传递 const Type & arg
  3. 右值引用传递 Type && arg

右值引用传递进来的参数由于已经有了参数名字,再传给下一级被调用函数时就会被当成左值。因为这个参数在调用函数后仍然可以继续使用,而右值的特点是该右值一旦传递给子函数之后,就不会在本函数内再次使用。

而std::forward告诉编译器,我的这个参数,在转发给子函数(或者是成员变量的构造函数)后,不再使用。这样才能被当成右值传递过去。

但是如果接收的参数是引用,那么代表着外界可能会有地方仍然用到这个被引用的变量,所以不能说“我不用了”就代表这个值可以当右值,因为不能保证外界有没有在用,所以引用类型的参数,在forward时仍然是被当成左值使用。

传右值的含义是“本调用方函数放弃对该变量的内容的所有权,未来不会再用该变量”。

你可能感兴趣的:(完美转发)