forward和move

forwrad和move

std::move一定会将实参转换为一个右值引用,并且使用std::move不需要指定模板实参,模板实参是由函数调用推导出来的。而std::forward会根据左值和右值的实际情况进行转发,在使用的时候需要指定模板实参。

  • std::move无条件转换到右值。就其本身而言,它没有move任何东西。
  • std::forward只有在它的参数绑定到一个右值上的时候,它才转换它的参数到一个右值。
  • std::move和std::forward在运行期都没有做任何事情
#include<iostream>
using namespace std;
template<typename T>
void print(T& t)
{
    cout << "lvalue" << endl;
}

template<typename T>
void print(T&& t)
{
    cout << "rvalue" << endl;
}

template<typename T>
void TestForward(T && v)     //万能引用
{
    print(v);
    print(std::forward<T>(v));
    print(std::move(v));
    printf("=============\n");
}

int main()
{
    TestForward(1);
    int x = 1;
    TestForward(x);
    return 0;
}
/*	输出
lvalue
rvalue
rvalue
=============
lvalue
lvalue
rvalue
=============
*/

第一个传入的1是一个右值, 在TestForward()中,由于所有形参都是左值,所以v是左值; forward保持了传入的实参,std::forward(v)就保持了右值, move强制转成右值

第二个传入的x是一个左值,在TestForward()中,由于所有形参都是左值,所以v是左值; forward保持了传入的实参,std::forward(v)就保持了左值, 而move会强制转成右值

所有形参都是左值

注意:一般而言,forward是要与万能引用一起使用,使用推导出来的模板参数类型在引用折叠后作为强转目标类型(保持实际传入参的左右值属性)

理解原理:(自己理解,若有错误,敬请指出)

forward 相当于 static_cast<T&&>(v);

template<typename T>
void TestForward(T && v) 
{ 
  print(static_cast<T&&>(v)); 
}


即将v强制转换成T&&的类型,这和v本身是左值还是右值无关,和模板的参数类型有关,模板的类型参数的T是万能引用,若传入的实际参数是左值,就是T&,若传入的实参是右值,则推导出来的是T&&。(这里指的是模板里的 T=T& 或 T=T&&)
  之后在static_cast<T&&>  会再次发生引用折叠
  若模板参数推导出来的是 T&  引用折叠就是(将static_cast<T&&>里的T换成T&) T& && 就还是左值引用
  若模板参数推导出来的是 T&&  同理  T&& && 就还是右值 (书里说这要得到的就是一个右值,而不是右值引用,不太理解)
  
  

posted @ 2023-03-09 15:38  预期  阅读(53)  评论(0)    收藏  举报