IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 中的万能引用、引用折叠、完美转发 -> 正文阅读

[C++知识库]C++ 中的万能引用、引用折叠、完美转发

在学习c++过程中,相信不少同学都或多或少的听过万能引用、引用折叠、完美转发,介绍这几个概念之前,首先列举下左值和右值的概念;

左值和右值:

顾名思义,可以简单的理解为在等号左边的值是左值,再等号右边的值是右值,例如 int a = 1,那个a就是左值,而1就是右值,左值可以用&标志符取地址,右值不行;另外,临时变量也是属于右值,例如:

using namespace std;
class A
{

};

int main()
{
	A a = A();
}

这里a是左值,A()是属于临时变量,是属于右值

左值引用和右值引用:

左值引用用一个&符号进行标志,例如

int main()
{
	int a = 10;
	int & left_value = a;
	//或者用const修饰
	const int& left_value1 = 100;
}

这里left_value就是左值引用, left_value1也是左值引用,由于有const进行修饰,所以可以直接赋右值;


右值引用用标志符号&&表示,例如

int main()
{
	int&& a = 100;
}

这里right_value就是右值引用。
这里小结一下,其实无论是左值、右值还是左值引用、右值引用,都是一种类型,就可我们平时定义类型int float、double等一样,都对应这一种定义,知道他们是不用的类型就可以。

万能引用:

万能引用通常是在模板中使用,例如T &&这种模板的定义,它既可以接受左值,右值,也可以接收左值引用、右值引用作为参数,所以成为万能引用,而且在使用的过程中,我还发现这种可以不用给定模板类型,说明使用万能引用可以实现自动推断,如下面的例子:

#include<iostream>
using namespace std;

template<typename T>
void print(T& a)  // 接受左值
{
	cout << "左值" << endl;
}

template<typename T>
void print(T&& a) //接受右值
{
	cout << "右值" << endl;
}

template<typename T>
void forwardTest(T&& v)
{
	print(v);
	print(move(v));
	print(forward<T>(v)); //利用std::forward<T>(u)进行转发,当且仅当T为左值引用时,u被转换为左值
	//引用,否者全都转换为右值引用
}

int main()
{
	int a = 10;
	string s = "asd";
	forwardTest(a);
	cout << "------------------" << endl;
	forwardTest(move(s));
}

/*
输出为:
左值
右值
左值
------------------
左值
右值
右值*/

在模板函数 forwardTest中,模板参数类型是T && ,这个就是万能引用的标志,然后我们可以用这个函数把穿进去参数,根据左值和右值进行完美转发。

引用折叠:

所谓的引用折叠,就是当有多个&标志的时候,进行类型的推断,规则是当且仅当T的类型是&& 右值的时候,根据引用折叠推断出来的类型是右值,否者都是左值引用,例如
转换规则是:

  • && && ==> &&
  • & && ==> &
  • && ==>&

或者换种说话就是:

  • 当T的类型是 int &&,代入万能引用模板就是 int && &&,等价于int &&,也就是右值引用。
  • 当T的类型是int &,代入万能引用模板就是 int & && ,等价于iint &,也就是左值引用。
  • 当T的类型是int ,代入万能引用模板就是 int &&,这个等价于int &,也就是左值引用。

上面三类就是引用折叠的定义。

完美转发:

所谓的完美转发,就是当我传左值和右值引用到模板函数中时,在模板函数中使用这个参数,要能够区分左值和右值引用,在使用std:forward之前会有什么问题呢,还是上面万能引用中提到的代码,如下:

#include<iostream>
using namespace std;

template<typename T>
void print(T& a)  // 接受左值
{
	cout << "左值" << endl;
}

template<typename T>
void print(T&& a) //接受右值
{
	cout << "右值" << endl;
}

template<typename T>
void forwardTest(T&& v)
{
	print(v);
	print(move(v));
	print(forward<T>(v)); //利用std::forward<T>(u)进行转发,当且仅当T为左值引用时,u被转换为左值
	//引用,否者全都转换为右值引用
}

int main()
{
	int a = 10;
	string s = "asd";
	forwardTest(a);
	cout << "------------------" << endl;
	forwardTest(move(s));
}

/*
输出为:
左值
右值
左值
------------------
左值
右值
右值*/

在forwardTest函数中,第一个print函数的调用始终是左值,这是因为无论是左值还是右值,进入到函数中时,都会变成左值,为什么呢?因为它有了地址,所以就是左值了,所以为了解决这种问题,std:forward就开始显示它的作用了,我们需要利用到forward进行转发,让传进去的值,可以按照其左右值的类型进行分发,类似于上面代码的print,两个重载函数,可以根据参数类型进行对应的分发。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:05:06  更:2022-09-25 23:06:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:37:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码