一、万能引用

1、英文:Universal Reference  。

2、诞生的原因

因为 C++ 中存在左值引用和右值引用,导致若想同时实现既可传入左值又可传入右值的功能,需要对相同函数进行重载,导致代码冗余。

3、解决办法

为了解决上述问题,就诞生了万能引用,具体用法如下:

template<typename T>
void func(T&& param) {;
}

主要实现方法是依靠 C++ 强大的模板推导能力,在编译期间确定 param 是左值还是右值。

4、扩展

&&,在模板形参列表中代表万能引用,在其他地方就代表右值引用。

5、栗子

#include <iostream>template <typename T>
void func(T &&param)
{std::cout << param << std::endl;
}
int main()
{int num = 0;func(num);func(100);return 0;
}
0
100

二、引用折叠

1、英文:Reference Collapse 。

2、诞生的原因

模板函数:

template <typename T>
void func(T &param)
{std::cout << param << std::endl;
}template <typename T>
void func(T &&param)
{std::cout << param << std::endl;
}

函数形参由于有左值引用和右值引用之分,传入函数的数据也有左值引用和右值引用的区分,这就分出了 4 种情况。

但是 C++ 是不能对引用进行引用的,故需要一种方案,判定上述 4 种情况下最终的结果是左值引用还是右值引用。

3、解决办法

为了解决上述问题,诞生了引用折叠这个概念,也就是判定上述 4 种情况下最终的结果是左值引用还是右值引用的方案,如下:

形参 传入数据 结果
& & &
& && &
&& & &
&& && &&

可以发现,形参和传入数据只要有一个是左值引用,其结果就是左值引用;只有全部都是右值引用的情况下其结果才能是右值引用。

4、注意

引用折叠只能发生在模板函数中,即:编译期间。

5、栗子

#include <iostream>template <typename T>
void func_L(T &param)
{std::cout << param << std::endl;
}template <typename T>
void func_R(T &&param)
{std::cout << param << std::endl;
}int getvalue()
{return 100;
}
int main()
{int num = 0;int &&num_r = getvalue();func_L(num);func_L(num_r);func_R(num);func_R(200);return 0;
}
0
100
0
200

三、完美转发

1、英文:Perfect Forwarding 。

2、诞生的原因

经过上述引用折叠之后,传之前的数据的引用类型和传入之后的引用类型可能发生变化,怎么才能保持引用类型呢?如下:

#include <iostream>template <typename T>
void func(T &param)
{std::cout << "左值" << std::endl;
}
template <typename T>
void func(T &&param)
{std::cout << "右值" << std::endl;
}template <typename T>
void warp(T &&param)
{func(param);
}int main()
{int num = 0;warp(num);warp(100);return 0;
}
左值
左值

3、解决办法

为了解决上述问题,增加了完美转发的概念,即:经过转发之后,数据的引用类型恢复到之前的类型。

4、栗子

#include <iostream>template <typename T>
void func(T &param)
{std::cout << "左值" << std::endl;
}
template <typename T>
void func(T &&param)
{std::cout << "右值" << std::endl;
}template <typename T>
void warp(T &&param)
{func(std::forward<T>(param));
}int main()
{int num = 0;warp(num);warp(100);return 0;
}
左值
右值

(SAW:Game Over!)

Cpp 11 / 万能引用、引用折叠和完美转发相关推荐

  1. [c++]-c++中的左值和右值、左值引用和右值引用、万能引用和引用折叠及完美转发

    1.左值和右值 1.1左值和右值定义 在c++中,左值是一个指向内存的东西,换句话来讲,左值有地址,保存在内存中,右值则为不指向任何地方东西,即不在内存中占有确定位置.一般来说,右值是暂时和短暂的,而 ...

  2. C++ 中的万能引用、引用折叠、完美转发

    在学习c++过程中,相信不少同学都或多或少的听过万能引用.引用折叠.完美转发,介绍这几个概念之前,首先列举下左值和右值的概念: 左值和右值: 顾名思义,可以简单的理解为在等号左边的值是左值,再等号右边 ...

  3. C++右值引用与转移和完美转发

    C++右值引用与转移和完美转发 1.右值引用 1.1右值 lvalue 是 loactor value 的缩写,rvalue 是 read value 的缩写 左值是指存储在内存中.有明确存储地址(可 ...

  4. Cpp / 通用引用、引用折叠与完美转发问题

    一.通用引用 通用引用,允许其绑定右值(就像右值引用那样)和左值(就像左值引用那样).而且,它们可以绑定 const 或者非 const 对象,可以绑定 volatile 和非 volatile 对象 ...

  5. 通用引用、引用折叠与完美转发问题

    一.通用引用: 通用引用(universal reference)是Scott Meyers在C++ and Beyond 2012演讲中自创的一个词,用来特指一种引用的类型.这种引用在源代码中(&q ...

  6. C++11更新内容(2)--完美转发--默认移动构造/移动赋值--1116

    1.完美转发 1.1万能引用 void Fun(int &x){ cout << "左值引用" << endl; } void Fun(const ...

  7. C++11新特性之 std::forward(完美转发)

    上篇博客对右值.右值引用都做了简要介绍. 我们也要时刻清醒,有时候右值会转为左值,左值会转为右值. (也许"转换"二字用的不是很准确) 如果我们要避免这种转换呢? 我们需要一种方法 ...

  8. C++11特性《 右值引用-<完美转发>、lambda表达式》

    1.右值引用 1.1移动语义 如果一个类中涉及到资源管理,用户必须显式提供拷贝构造.赋值运算符重载以及析构函数,否则编译器将 会自动生成一个默认的,如果遇到拷贝对象或者对象之间相互赋值,就会出错,比如 ...

  9. 【C++】右值引用、移动语义、完美转发(下篇)

    上篇中,主要讲解了右值引用和移动语义的具体定义和用法.在C++11中几乎所有的容器都实现了移动语义,以方便性能优化.本文以C++11容器中的insert方法为例,详细讲解在容器中移动语义是如何提高性能 ...

最新文章

  1. mongodb 内建用户
  2. Pycharm中tensorflow框架下tqdm的安装
  3. Putty添加SSH Key
  4. 【排序】插入类排序—(折半)插入排序、希尔排序
  5. python中read()、readline()、readlines()函数
  6. 《数字图像处理》 笔记
  7. 草珊瑚理解IFC(inline formatting context)
  8. python win7 win10_Python如何获取Win7,Win10系统缩放大小
  9. token的作用_说一说Coin和Token有什么不同
  10. CodeForces 173B Chamber of Secrets(最短路)
  11. 简述prototype, _proto_, constructor三者的关系
  12. python爬虫解决频繁访问_python爬虫程序如何预防被限制
  13. 视频直播方案(加强版
  14. 教大家一个可以用迅雷全速下载百度网盘文件的方法
  15. Linux-ubuntu系统查看显卡型号、显卡信息详解、显卡天梯图
  16. 折腾了好久 ORA-00904: : 无效的标识符
  17. 史上最全的HTML、CSS知识点总结,浅显易懂。适合入门新手
  18. 想从动物科学转专业去计算机,动物科学转专业或者加第二专业动物医学,望老师同学们提些建议。...
  19. 浙江台州“安乐死”案承办法官首次披露庭审细节
  20. 项目管理(PMP)精选题精讲

热门文章

  1. angular 动态取到的html片段 在页面的展示
  2. 【Unity】第8章 GUI开发
  3. 关于css3的自定义字体
  4. 自定义Interpolator
  5. SEPM嵌入式数据库损坏的一种修复方法及sem5.log的缩小方法
  6. Linux文件预读对系统的影响
  7. 开发常见错误解决(1)注册.NET EnterpriseServices COM+组件,事务服务不可用
  8. 软件测试BUG参考标准
  9. 转换string_类型转换详解
  10. Vue项目如何提高效率?大厂2大实践总结告诉你