一、概念
原型:
template<typename _Tp> constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept { return static_cast<_Tp&&>(__t); } template<typename _Tp> constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type&& __t) noexcept { static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" " substituting _Tp is an lvalue reference type"); return static_cast<_Tp&&>(__t); }
std::forward被称为完美转发,它的作用是保持原来的值属性不变。啥意思呢?通俗的讲就是,如果原来的值是左值,经std::forward处理后该值还是左值;如果原来的值是右值,经std::forward处理后它还是右值。
个人理解就是:std::move虽然能将一个左值转为右值,但是通过右值引用来引用这个右值之后,这个右值引用就变成了左值,是有地址的,forward就是用来避免这种情况,左/右值无论怎么转发都是左/右值二、使用
#include <iostream> template<typename T> void print(T & t){ std::cout << "左值" << std::endl; } template<typename T> void print(T && t){ std::cout << "右值" << std::endl; } template<typename T> void testForward(T && v){ print(v); print(std::forward<T>(v)); print(std::move(v)); } int main(int argc, char * argv[]) { testForward(1); std::cout << "======================" << std::endl; int x = 1; testFoward(x); } //clang++ -std=c++11 -g -o forward test_forward.cpp
打印:
第一组:
传入的1虽然是右值,但经过函数传参之后它变成了左值(在内存中分配了空间);而第二行由于使用了std::forward函数,所以不会改变它的右值属性,因此会调用参数为右值引用的print模板函数;第三行,因为std::move会将传入的参数强制转成右值,所以结果一定是右值。
第二组:
因为x变量是左值,所以第一行一定是左值;第二行使用forward处理,它依然会让其保持左值,所以第二也是左值;最后一行使用move函数,因此一定是右值
参考:https://www.jianshu.com/p/97fdd852974f