【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=10;
    func1(10);      //右值
    func1(a);       //右值
    return 0;
}

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

void func1(const  int& z){}

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

运行结果:

image

当调用了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=10;
    func1(10);      //右值
    func1(a);       //右值
    return 0;
}

再次运行:

image

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

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

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

相关文章
|
12小时前
|
NoSQL 程序员 编译器
|
12小时前
|
存储 消息中间件 NoSQL
C++中使用解除引用运算符访问指向的数据
C++中使用解除引用运算符访问指向的数据
|
12小时前
|
存储 Kubernetes NoSQL
|
12小时前
|
消息中间件 Kubernetes NoSQL
|
12小时前
|
存储 Kubernetes NoSQL
|
12小时前
|
存储 安全 编译器
C++入门:引用是什么
C++入门:引用是什么
|
12小时前
|
安全 Java 编译器
|
12小时前
|
编译器 C语言 C++
|
12小时前
|
安全 编译器 C++
C++引用详解
C++引用详解
14 0
|
12小时前
|
存储 安全 编译器
【C++初阶】引用&内联函数&auto关键字&范围for循环&nullptr
从上篇文章我们开始分享C++的一些入门基础知识,讲到了关键字、命名空间等一些基础问题,今天我们继续分享一些基础知识,让大家更深入的入门C++。
相关产品
云迁移中心
推荐文章
更多