【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){}

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

运行结果:

当调用了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;
}

再次运行:

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

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

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

相关文章
|
1天前
|
安全 C++
|
6天前
|
C++
C++引用
C++引用
6 1
|
6天前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
33 5
|
13天前
|
C++
C++对C的改进和拓展\引用
C++对C的改进和拓展\引用
9 0
|
15天前
|
C++
C++的引用定义语法和应用
C++的引用定义语法和应用
|
18天前
|
存储 安全 编译器
【C++入门】—— C++入门 (中)_引用
【C++入门】—— C++入门 (中)_引用
22 5
|
19天前
|
C语言 C++ 编译器
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
|
20天前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
21 1
|
25天前
|
安全 测试技术 C++
C++中的引用
C++中的引用
10 1
|
27天前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
14 2