【1++的C++进阶】之C++11(一)

news2024/11/26 2:24:28

👍作者主页:进击的1++
🤩 专栏链接:【1++的C++进阶】

文章目录

  • 一,前言
  • 二,列表初始化
  • 三,声明
    • 自动类型推断(auto)
    • decltype
    • nullptr
  • 四,右值引用
  • 五,完美转发

一,前言

C++11带来了哪些变化?

相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。

二,列表初始化

在C++11之前,我们使用花括号{ }对数组或者结构体进行列表初始值设定。在C++11中,扩到了花括号的使用范围,使其可以用于所有的内置类型,也可以用于自定义类型,并且可以省略’='。

示例代码如下:

//C++11之前
	int arr[] = { 1,2,3,4 };
	struct A
	{
		int a;
		int b;
	};

	A a = { 1,2 };
	Date d1(2033, 9, 11);

	//C++11
	int a = { 2 };
	int b{ 3 };
	int arr2[]{ 1,2,3,4 };
	int* p = new int[4]{ 1,2,3,4 };
	Date d2{ 2023,9,11 };//使用列表初始化方式调用构造函数

std::initializer_list
std::initializer_list是一种类型,其一般作为构造函数的参数,这样使用花括号初始化对象就更方便了
下面是在vector中使用inittializer_list进行构造的模拟实现:

vector(initializer_list<T> il)
		{
			_start = new T[il.size()];
			_finish = _start + il.size();
			end_of_storage = _start + il.size();
			iterator val = _start;
			typename initializer_list<T>::iterator it = il.begin();
			while (it != il.end())//利用迭代器进行赋值
			{
				*val = *it;
				it++;
				++val;
			}
		}

三,声明

自动类型推断(auto)

auto可以根据我们初始化的值自动类型推断,可以简化我们的代码,但其前提是必须对变量进行初始化。如自动推断迭代器类型。。。

vector<int> v;
	auto it = v.begin();
	auto a = 1;

但是,要注意的是其不能用在数组,参数列表,模板参数中。

decltype

decltype关键字可以将变量的类型声明为表达式的类型。
如下:

	int a =1;
	double b = 2;
	decltype(a * b) ret;


template<class T1, class T2>
void Func(T1 t1, T2 t2)
{
	decltype(t1 * t2)ret;
	cout << typeid(ret).name() << endl;
}

在这里插入图片描述

nullptr

在C++中NULL被定义为字面量0,由于0既能表示空指针,又能表示整型,所以会有歧义,因此,有了nullptr来表示空指针。

四,右值引用

什么叫右值引用呢?
在了解右值引用之前,我们先来了解左值引用。
我们之前所使用的引用就叫做左值引用,左值是一个表示数据的表达式,我们能够获取它的地址以及对其进行赋值。左值可以出现在赋值符号的左边,右值不能出现在赋值符号的左边。当左值有const修饰时,其不能赋值,但可以取地址。给左值取别名就是左值引用。
右值也是一个表示数据的表达式,右值可以出现在赋值符号的右边,不能出现在赋值符号的左边,而且右值不能取地址。

右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址。

左值引用只能引用左值,不能引用右值。
但是const左值引用既可引用左值,也可引用右值

	int a = 0;
	int& b = a;
	int& c=10;
	const int&& d = 10;
	const int& e = a;

右值引用只能右值,不能引用左值。
但是右值引用可以move以后的左值

move()函数可以将左值强转换为右值

	int a = 0;
	int&& b = a;//不可以
	int&& c = move(a);

为什么要有右值引用?
首先const左值引用是可以引用右值的,但左值引用是有缺点的。
当我们返回的对象是一个临时对象,或是一个局部对象,出了作用域就会销毁,这时就不能左值引用返回了,得要进行拷贝构造,所以,效率会比较低。
为了解决上述问题,便有了移动构造和移动赋值。

我们来看下面这段代码:

class string
	{
	public:
		string(const char* str = "")
			:_str(nullptr)
		{
			cout << "string(const char* str)" << endl;
		}

		//拷贝构造
		string(const string& s)
			:_str(nullptr)
		{
			string tmp(s._str);
			std::swap(_str, tmp._str);
			//....
			cout << "string(const string& s)" << endl;
		}

		//移动构造
		/*string(string&& s)
		{
			std::swap(s._str, _str);
			cout << "string(string&& s)" << endl;

		}*/

		//赋值重载
		string& operator=(string& s)
		{

			std::swap(s._str, _str);
			cout << "string& operator=(string& s)" << endl;
			return *this;

		}

		//移动赋值
		string& operator=(string&& s)
		{
			std::swap(s._str, _str);
			return *this;
		}

		string to_string()
		{
			string str;
			///,.....
			return str;
		}


	private:
		char* _str;
	};

	void test6()
	{
		string s1("yetw");
		//string s2(s1);
		string s3(s1.to_string());
	}

当我们将移动构造屏蔽后,我们来观察结果
在这里插入图片描述
我们发现其调用了三次构造函数,一次拷贝构造。
其中,三次构造函数分别是:s1,to_string中的str,拷贝构造中的tmp这三个对象取调用。每一次调用都需要进行深拷贝,所以效率就会比较低。

我们再来观察有移动构造时的结果:
(to_string的返回值是一个
在这里插入图片描述
其调用了两次构造函数和一次移动构造。这两次构造函数分别s1,to_string中的str这两个对象去调用。

对比我们发现。有了移动构造后,减少了深拷贝的次数,效率自然就提高了。
接下来,我们就移动构造的原理进行剖析。
仍对于上述的操作来说,若没有移动构造,则to_string中的str由于是局部变量,因此不能引用返回,所以要拷贝构造出一个临时对象,再用临时对象对s3进行拷贝构造,在拷贝构造中,仍要进行一次构造,创建出临时对象tmp。由于编译器的优化,因此第一次拷贝构造被优化掉,就减少了一次拷贝构造。
当有移动构造时,to_string中的str移动构造出一个临时对象,这个临时对象再进行移动构造,将资源转移给s3。由于编译器的优化,资源会直接由str转移给s3。因此就只有一次移动构造。

总结一下:移动构造与移动赋值其实就是资源的转移,对于一个将亡的对象,其自身对资源没有利用,会造成浪费,我们将其资源转移出去,进行利用,这样就可以减少深拷贝的次数,增加效率了。

五,完美转发

来看以下代码:

void func(int& t)
	{
		cout << "左值引用" << endl;
	}

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

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

	void func(const int&& t)
	{
		cout << "const 右值引用" << endl;
	}

	template<class T>
	void to_func(T&& t)
	{
		func(t);
	}
/
	hyp::to_func(1);
	const int a = 3;
	hyp::to_func(a);
	hyp::to_func(move(a));

在这里插入图片描述
根据上述结果我们可以得出以下结论:

  1. 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
  2. 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
  3. 引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值

因此,为了保持它的左值,右值属性,我们便有了完美转发。

void func(int& t)
	{
		cout << "左值引用" << endl;
	}

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

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

	void func(const int&& t)
	{
		cout << "const 右值引用" << endl;
	}

	template<class T>
	void to_func(T&& t)
	{
		func(std::forward<T>(t));
	}
/
	hyp::to_func(1);
	const int a = 3;
	hyp::to_func(a);
	hyp::to_func(move(a));

在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1005320.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker容器技术实战-2

03docker hub 首先注册上号&#xff1a; https://hub.docker.com/ 上传自己的镜像仓库 创建自己的仓库 webserver 拉取镜像 配置加速器 04搭建私有仓库 上传镜像 在主机1上 在主机2 上 激活内核选项 激活内核选项文件传输过去 配置使用非加密端口 05 docker私有仓库 仓库加…

机器学习笔记自最优化理论与方法(十一)无约束优化问题——关于共轭方向法重要特征的相关证明

机器学习笔记之最优化理论与方法——关于共轭方向法重要特征的相关证明 引言回顾&#xff1a;共轭方向法的思想与几何解释共轭方向法的重要特征(2023/9/12)共轭方向法重要特征的证明 引言 上一节介绍了共轭方向法的朴素思想与几何意义。本节将继续介绍共轭方向法的重要特征以及…

如何判断一篇论文有没有被SCI收录?

打开 Web of Science 网站设置 SCI 筛选条件&#xff08;因为 WoS 收录的不只是 SCI&#xff09; 3. 输入论文题目&#xff0c;点击搜索

如何有效地设置示波器衰减比

在电子电路实验时&#xff0c;往往需要搭配测量设备方可检验电路可行性、了解电路实时动态。示波器是常见的测量设备之一&#xff0c;而搭配示波器使用的测量工具却有很多&#xff0c;如常见标配的无源电压探头、测输出端电压的有源差分探头、测某点电流信号的电流钳等等。 由…

【玩儿】Win 11 安装安卓子系统

Win 11 安装安卓子系统 一、Android子系统的要求二、配置 Windows 虚拟化支持三、Win11 正式版安装安卓子系统方法教程 (离线包安装)下载离线包安装子系统 四、软件安装应用商店下载ADB 调试模式下安装打开调试模式&#xff08;开发人员模式&#xff09;下载 ADB 调试工具ADB 配…

类和对象续

目录 包 自定义包 包的访问权限控制 常见的包 Static成员 静态成员变量 静态成员方法 代码块 构造块 静态块 重写 继承 继承是啥&#xff1f; 父类成员访问 子类中访问父类成员变量 两者不同名 两者同名 子类中访问父类对的成员方法 super 子类构造方法 …

浮点型数据在内存中是如何存储的

文章目录 浮点型变量的存储规则&#xff1a;浮点数怎么转化为二进制浮点型数据在内存中的存储E不全为0或不全为1E为全0E为全1 浮点型变量的存储规则&#xff1a; 根据国际标准IEEE&#xff08;电气和电子工程协会&#xff09; 754&#xff0c;任意一个二进制浮点数V可以表示成下…

java判断两个时间是不是同一天的方法、Java中判断是否是当天时间

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 热爱技术的小郑 前言 开发中会遇到这样一…

简简单单教你如何用C语言实现获取当前所有可用网口!

一、获取本机所有可用网卡名 原理&#xff1a; 在 Linux 系统中&#xff0c;/proc 目录是一个位于内存中的伪文件系统。 /proc目录是内核提供给我们的查询中心&#xff0c;通过查询该目录下的文件内容&#xff0c;可以获取到有关系统硬件及当前运行进程的信息&#xff0c;如…

【C++基础】左值引用、右值引用、move、forward

本文参考&#xff1a;右值引用 | 爱编程的大丙 转移和完美转发 | 爱编程的大丙 左值、右值、左值引用、右值引用 左值 是指存储在内存中、有明确存储地址&#xff08;可取地址&#xff09;的数据&#xff1b; 右值 是指可以提供数据值的数据&#xff08;不可取地址&#x…

阶乘的素因数分解

一、题目 整除问题_牛客题霸_牛客网 (nowcoder.com) 二、普通数字的素因数分解 假如对n进行素因数分解。先利用素数筛法筛选出0~n范围内的全部素数。然后依次遍历这些素数&#xff0c;用n除以这些素数&#xff0c;直至无法整除。然后接着用下一个素数作为除数&#xff0c;直到n…

重庆OV证书和EV证书有什么区别

SSL数字证书按照保护的域名数量和类型可以分为单域名SSL证书、多域名SSL证书和通配符SSL证书三种&#xff0c;按照验证方式可以将SSL数字证书分为DV基础型SSL证书、OV企业型SSL证书和EV增强型SSL证书三种。今天就随SSL盾小编了解OV证书和EV证书的区别。 1.OV企业型SSL证书由CA…

Linux学习总结

Linux学习目标&#xff1a; Linux操作系统介绍与安装。 Linux常用命令。 Linux常用软件安装。 Linux网络。 防火墙。 Shell编程等。 *******************************LinuxOS介绍与安装************************************ Linux OS介绍与安装 Linux是什么&#xff…

C# 去除utf-8 BOM头

static void Main(string[] args) {var a1 Encoding.UTF8.GetBytes("<");var a2 Encoding.UTF8.GetBytes("&#xfeff;<");Console.WriteLine("去除utf-8 bom之前");Console.WriteLine(Encoding.UTF8.GetString(a1));Console.WriteLine(…

黑马 小兔鲜儿 uniapp 小程序开发- 推荐模块- day03

黑马 小兔鲜儿 uniapp 小程序开发- 02首页模块_软工菜鸡的博客-CSDN博客 小兔鲜儿 - 推荐模块- day03 主要实现 Tabs 交互、多 Tabs 列表分页加载数据。 动态获取数据 参考效果 推荐模块的布局结构是相同的&#xff0c;因此我们可以复用相同的页面及交互&#xff0c;只是所…

轻松打造自己的ChatGPT应用,AI应用,源码附赠

这里写自定义目录标题 前言简介 前言 大家好&#xff0c;我是静幽水&#xff0c;目前是一名大厂全栈工程师&#xff0c;练习时长两年&#xff0c;擅长Java后端&#xff0c;Vue前端&#xff0c;小程序编程&#xff0c;Python编程&#xff0c;ChatGPT 提示词等技术。现在正在系统…

建筑模板木模好还是钢模好

在建筑施工中&#xff0c;模板是一项关键的工程&#xff0c;对于建筑结构的质量和施工效率起着重要作用。在选择模板材料时&#xff0c;木模和钢模都是常见的选择。本文将比较木模和钢模的优缺点&#xff0c;以帮助您做出明智的选择。 正文&#xff1a;一、木模&#xff1a;传统…

信创国产化解决方案

近年来&#xff0c;随着信息技术的飞速发展&#xff0c;信创产业成为国家发展的重要战略之一。2018年以来我国将信创纳入国家战略&#xff0c;提出了“28”发展体系&#xff0c;随后扩展至更多行业&#xff0c;演变为“28N”应用体系。2023年中国信创产业逐步走向应用落地阶段。…

sql函数实现模糊精确匹配

sql函数实现模糊精确匹配 例如&#xff1a; 查询的时候匹配[‘1’] 就只匹配1的 &#xff0c;而不是15的也会模糊查询进去 slq函数如下&#xff1a; CREATE OR REPLACE FUNCTION does_string_array_intersect ( target_string TEXT, input_strings TEXT [] ) RETURNS BOOLEA…

单元格法求解多边形最大内接矩形问题【思路讲解+java实现】

问题描述 给定一个多边形的点集&#xff0c;希望找出多边形内部面积最大的矩形。该问题可能出现在&#xff0c;从一个多边形废料上面切割出一个最大的矩形&#xff0c;该矩形可以重复利用&#xff0c;解决该问题可以节约原材料&#xff0c;降低企业运作成本 问题解决方案 本…