【c++11】万能引用和完美转发

c++11

  • 万能引用
  • 完美转发

这一节是对上一篇右值引用的补充。

链接: 右值引用

万能引用

看如下代码

void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }

void Fun(int &&x){ cout << "右值引用" << endl; }

fun()函数进行了重构,当我们调用函数时,编译器会根据我们的实参来判断调用最匹配的函数,这是的大家都知道的事情。
但是,
模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值
当传右值时,正常调用
当传递左值时,&& 会进行折叠,所以也叫折叠引用
看接下来的代码:

template<class T>
void func1(T&& z)
{
	fun(z);
}

int main()
{
	int a=10func1(10);      //右值
	func1(a);       //右值
    return 0}

同时传左值和右值,也可以正常运行,当然

void func1(const  int& z){}

也可以成功调用上述代码,但是该方法无法保存实参的右值属性,在传递过程中就改变了参数的属性。

运行结果:
在这里插入图片描述
当调用了fun()函数后,怎么显示的都是左值引用

怎么回事呢?

要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是ref引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感觉很神奇。

10    //纯右值
int&& ref=10;  //  ref是一个左值

所以当右值传递给z后,z已经是一个左值了,所以最后的结果是打印出两次的左值引用。
那么如何解决呢?

就需要学习接下来的完美转发。

完美转发

std::forward 完美转发在传参的过程中保留对象原生类型属性。

template<class T>
void func1(T&& z)
{
	fun(forward<T>(z));
}
int main()
{
	int a=10func1(10);      //右值
	func1(a);       //右值
    return 0}

再次运行:
【c++11】万能引用和完美转发_第1张图片

可以看出,一个右值引用一个左值引用,保持对象原生属性类型。

这对右值引用做了很好的一个补充,我们在实习一些比较复杂的项目中,在某一个函数复用函数是很常见的行为,经常叠加了好几层复用,如果传递右值,就需要完美转发来保存其原生属性。

注意:对每一层的调用都需要进行一次完美转发:forward(),否则参数的原生属性还是会改变。

你可能感兴趣的:(c++,开发语言,右值引用)