【c++修行之路】c++11特性--上

news2024/11/26 10:15:45

文章目录

  • 前言
  • 列表初始化
    • 用法介绍
    • 原理:std::initializer_list
  • 简化声明的方式
    • auto
    • decltype
  • 右值引用
  • 移动构造
  • 万能引用和完美转发
    • 万能引用
    • 完美转发
  • 类的新增功能
  • 可变参数模板
  • lambda表达式
  • 深入探究lambda表达式
  • lambda表达式带来的便利
  • 结语

前言

大家好久不见,今天带大家一起了解一下关于c++11的新特性。

列表初始化

用法介绍

c++ 98允许使用花括号对数组和结构体元素统一的初始化,而c++ 11扩大了花括号初始化范围,使得可以对所有的自定义类型都初始化,使用初始化列表的时候,可以使用等于号( = ),也可以省略等于号( = )。

int a{ 0 };
int arr[10]{ 1,2,3,4,5,6,7,8,9 };
Date d1{ 2023,5,29 };
Date d2{ 2023,5,30 };
Date d3 = { 2023,6,3 };
d1.show();
d2.show();

原理:std::initializer_list

为什么能支持使用大括号来初始化,在c++11之后,所有的stl容器都增加了一个构造方法的重载,原理就是将花括号的内容构造一个initializer_list的类,拿这个类去调用对应的构造方法。

auto i1 = { 1,2,3,4,5 };
initializer_list<int>::iterator it1 = i1.begin();

//初始化列表在常量区,不能被更改
*it1 = 1;//这样是非法的

在这里插入图片描述

简化声明的方式

auto

由编译器自动推导类型。

//示例:
auto i1 = { 1,2,3,4,5 };

注意:
1、auto不能作参数类型
2、auto不能当函数返回值的类型

decltype

作用:将变量的类型声明为表达式的类型。

//示例:
template<class T1,class T2>
void func(T1 t1,T2 t2)
{
	decltype(t1 * t2) ret;
	cout << ret << endl;
}

右值引用

之前介绍c++入门的时候我们讲过一次引用,我们把之前的引用成为左值引用。左值引用和右值引用都是给一个变量起别名。

左值:可以获取它的地址 +可以对其赋值,能够出现在赋值符号的左边。
左值引用:给左值起别名。

右值:不能获取他的地址,字面常量,表达式返回值,函数返回值(除左值引用的返回),不能出现在赋值号的左边!
右值引用:给右值取别名。

int main()
{
	double x = 1.1;
	double y = 2.3;

	10;
	x + y;
	Sum(x, y);

	int&& r1 = 10;
	double&& r2 = x + y;
	double&& r3 = Sum(x, y);

	const int& r4 = 10;


	return 0;
}

可以看出:
1、const左值引用可以引用左值也可以引用右值。
2、普通左值引用只可以引用左值,不能引用右值。
3、右值引用可以引用move后的左值。

移动构造

纯右值:字面量等(true,false,1.2)。
将亡值:生命周期就要结束的资源。

所谓移动构造,就是窃取将亡值的资源来构造自己。

c++编译器一般优化:两个连续的构造优化为直接构造、两个连续的拷贝构造优化成直接拷贝构造。用右值引用的方式解决了左值引用留下来的问题:
1、函数中的资源不能使用左值引用返回提高资源利用率

在这里插入图片描述
移动构造的实现:

//移动构造:

// 拷贝构造
string(const string& s)
	:_str(nullptr)
{
	cout << "string(const string& s) -- 深拷贝" << endl;

	string tmp(s._str);
	swap(tmp);
}

// 移动构造
string(string&& s)
	:_str(nullptr)
{
	cout << "string(string&& s) -- 移动拷贝" << endl;
	swap(s);
}
//============================================================
//移动赋值:

// 赋值重载
string& operator=(const string& s)
{
	cout << "string& operator=(string s) -- 深拷贝" << endl;
	string tmp(s);
	swap(tmp);

	return *this;
}

// s1 = 将亡值
string& operator=(string&& s)
{
	cout << "string& operator=(string&& s) -- 移动赋值" << endl;
	swap(s);

	return *this;
}

所以,移动构造和移动赋值是通过直接移动资源来提高效率。

万能引用和完美转发

万能引用

模板中的&&不代表右值引用,而是万能引用,既能接收左值又能接收右值。
接收之后都退化为左值。
为了在传递过程中保持他的左值或右值属性,需要使用完美转发。

完美转发

为了解决上面万能引用带来右值属性退化的问题,就需要使用完美转发
std::forward 完美转发在传参的过程中保留对象原生类型属性。

类的新增功能

新增两个默认成员函数:默认移动构造和默认移动赋值,但这两个函数触发条件都比较苛刻:

条件:
1、没有自己实现移动构造/移动赋值
2、没有实现析构、拷贝构造、拷贝赋值重载的任何一个

满足上述条件,这个类会自动生成一个默认的移动拷贝和移动赋值函数,和默认实现的构造函数相似
对于内置类型,执行逐成员按字节拷贝;对自定义类型,看这个成员是否实现移动构造,如果实现了就调用移动构造,如果没实现就调用拷贝构造。

可变参数模板

c++11 支持的可变参数模板让类模板和函数模板可以接收可变参数。

但可变参数的使用和C语言大不相同,我们需要一些特别的手段来获取这些参数:

// 递归终止函数
template <class T>
void ShowList(const T& t)
{
	cout << t << endl;
}

// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{
	cout << value << " ";
	ShowList(args...);
}

还有另一种不需要递归的方式来得到可变参数:

template<class T>
int PrintArg(T t)
{
	cout << t << " ";
	return 0;
}

template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { PrintArg(args)... };
	cout << endl;
}

//其实就是编译后:
template <class ...Args>
void ShowList(char a1,int a2,string a3)
{
	int arr[] = { PrintArg(a1),PrintArg(a2),PrintArg(a3)};
	cout << endl;
}

lambda表达式

书写格式:
[capture-list] (parameters) mutable-> return-type{statement}

[capature-list] : 捕捉列表,编译器根据[]判断接下来的代码是否是lambda函数,捕捉列表能捕捉上下文的变量供lambda函数使用。

(parameters) :参数列表,如果不需要参数传递,可以连带着()一起省略

mutable : 默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性,使用mutable时,参数列表不可省略。

->returntype :返回值类型,用追踪返回类型形式声明函数的返回值类型。没有返回值这部分可以省略,返回类型明确也可省略,由编译器自己推导。

{statement} : 函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

lambda表达式没有名字,若要使用需要使用可以用auto关键字命令lambda表达式 ,之后就可以显示调用这个lambda表达式了。

//使用示例:
auto sum = [a,b](int x,int y) ->int
{
	cout << a << " " << b << endl;

	cout << x + y << endl;
	return a + b;
};

捕捉列表描述了上下文哪些数据看了一被lambda使用以及使用的方式是传值还是传引用。

[=]:表示值传递方式捕获所有父作用域中的变量(包括this)。
[&]:表示引用传递方式捕获所有父作用域中的变量(包括this)。

[val] :表示值传递捕捉变量val。
[&val]:表示引用传递捕捉变量val。

[this] :表示值传递捕获当前的this指针。

注意:
1、父作用域指的是包含lambda函数的语句块。
2、捕捉列表可由多个捕捉项组成,以逗号分割。
[= , &a , &b] : 表示以引用方式捕捉ab,其他采用传值捕捉。
[& , a ,this] :表示以传值方式捕捉a和this指针,其他采用传引用捕捉。
3、捕捉列表不允许重复传递,否则编译报错。
4、块作用域以外的lambda函数捕捉列表必须为空
5、lambda表达式之间不能相互赋值,尽管看起来类型相同!

深入探究lambda表达式

大小:
使用sizeof关键字可以查看lambda表达式的大小

auto sum = [](int x,int y) ->int
{

};

std::cout << sizeof(sum) << std::endl;

打印结果为1
在没有捕获任何变量的时候,这个 lambda表达式的大小是1,这和我们没有任何变量的类大小是一样的。

汇编:
从汇编角度来看一下lambda表达式。

int a = 1;
int b = 2;

Sub sub;
sub();

auto sum = [a,b](int x,int y) ->int
{
	std::cout << a << " " << b << std::endl;

	std::cout << x + y << std::endl;
	return a + b;
};
sum(10,20);

从底层来看,lambda表达式也是与仿函数汇编一致的,可以看到这里lambda的类名是lambda_1,这也恰恰说明了就算lambda表达式写的一模一样,在底层看来也是两个不同的类,不能相互赋值。
在这里插入图片描述

lambda表达式带来的便利

int main()
{
	vector<int> v;
	v.push_back(20);
	v.push_back(10);
	v.push_back(30);

	sort(v.begin(), v.end(), [](const int x,const int y) {
		return x < y;
	});


	sort(v.begin(), v.end(), [](const int x, const int y) {
		return x > y;
	});

	return 0;
}

lambda相比于仿函数更加灵活,需要比较的条件可以自由变换。

结语

以上就是c++11新增特性上篇,我是蓝色学者i,希望对你有所帮助,我们下次再见。

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

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

相关文章

bmp文件格式与保存

BMP文件由三部分组成&#xff0c;分辨是文件头&#xff0c;DIM头和像素数据。具体格式如下&#xff1a; 基本介绍 1. 文件头 14个字节 signature&#xff1a; 为文件标志位&#xff0c;恒为0X42 FileSize&#xff1a;是指整个文件的大小 REservedx&#xff1a;保留位恒为0 …

leetcode700. 二叉搜索树中的搜索(java)

二叉搜索树中的搜索 leetcode700 二叉搜索树中的搜索题目描述 解题思路代码演示二叉树专题 leetcode700 二叉搜索树中的搜索 leetcode 700 二叉搜索树中的搜索。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/search-i…

chatgpt赋能python:Python去掉GIL:提升Python多线程编程性能的突破口

Python去掉GIL&#xff1a;提升Python多线程编程性能的突破口 Python 是世界上最受欢迎的编程语言之一&#xff0c;其中一大原因是其简单易用、优雅简洁的语法。Python 也是一个卓越的多用途编程语言&#xff0c;广泛应用于 Web 开发、科学计算、人工智能等领域。但是&#xf…

javaScript蓝桥杯-----宝贵的一票

目录 一、介绍二、准备三、目标四、代码五、检测踩坑&#xff01;&#xff01;六、完成 一、介绍 公司经常举办各种活动&#xff0c;但一到投票环节就犯了难&#xff0c;于是公司决定安排小蓝开发一个投票系统&#xff0c;更好的收集大家的投票信息。为了赶在下一次活动开始前…

k8s亲和性和反亲和性

1.前言 k8s的亲和性和反亲和性都是通过标签来影响pod的调度&#xff0c;在此基础上亲和性又分为硬亲和性和软亲和性&#xff0c;required为硬亲和性即标签内容必须要符合才能调度&#xff0c;preferred为软亲和性即标签内容不一定要符合也能调度&#xff0c;除此之外还有node亲…

Unsupported major.minor version 51.0解决办法

先看看我的报错截图 [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 08:51 min [INFO] Finished at: 2023-0…

[2.0快速体验]Apache Doris 2.0 日志分析快速体验

1. 概述 应用程序、服务器、云基础设施、IoT 和移动设备、DevOps、微服务架构—最重要的业务和 IT 发展趋势帮助我们以前所未有的方式优化运维和客户体验。但这些趋势也导致由机器生成的数据出现爆炸式成长&#xff0c;其中包括日志和指标等&#xff0c;例如&#xff0c;用户交…

Qcon 广州主题演讲:融云实时社区的海量消息分发实践

移步公众号文章 预约纸质版《作战地图》 5 月 26 日-27 日&#xff0c;QCon 全球软件开发大会落地广州。关注【融云全球互联网通信云】了解更多 融云 IM 服务架构师罗伟受邀分享“实时社区的海量消息分发实践”&#xff0c;从实践中来的前沿技术分享&#xff0c;收获现场开发者…

Nautilus Chain上首个DEX PoseiSwap即将开启IDO,潜力几何?

据悉&#xff0c;Nautilus Chain 上的首个 DEX PoseiSwap 即将开启 IDO &#xff0c;根据官方的最新公告显示&#xff0c;PoseiSwap 即将于 6 月 13 日至 6 月 14 日期间&#xff0c;在 Bounce 平台开启其治理通证 $POSE 的 IDO&#xff08;Initial DEX Offering&#xff09;&a…

openEuler Linux 部署 FineReport

openEuler Linux 部署 FineReport 部署环境 环境版本openEuler Linux22.03MySQL8.0.33FineReport11.0 环境准备 升级系统内核和软件 yum -y updatereboot安装常用工具软件 yum -y install vim tar net-tools 安装MySQL8 将 MySQL Yum 存储库添加到系统的存储库列表中 s…

【JavaEE】表白墙再升级(MySQL实现持久化)

表白墙再升级&#xff08;MySQL实现持久化&#xff09; 文章目录 【JavaEE】表白墙再升级&#xff08;MySQL实现持久化&#xff09;1. 后端引入JDBC的依赖2. 建库建表3. 编写数据库代码&#xff08;JDBC&#xff09;3.1 doGet方法改写3.1.1 构建本地数据源3.1.2 用本地数据源构…

移动端的轮播图

效果 技术选取 前端框架用的是vue3&#xff0c;使用的组件库为element-plus以及vant4 引入element-plus和vant4 安装element-plus cnpm install element-plus --save 安装按需导入 cnpm install -D unplugin-vue-components unplugin-auto-import 安装Vant cnpm i vant 按…

Fiddler抓包工具之fiddler的composer可以简单发送http协议的请求

一&#xff0c;composer的详解 右侧Composer区域&#xff0c;是测试接口的界面&#xff1a; 相关说明&#xff1a; 1.请求方式&#xff1a;点开可以勾选请求协议是get、post等 2.url地址栏&#xff1a;输入请求的url地址 3.请求头&#xff1a;第三块区域可以输入请求头信息…

图的简单理解

文章目录 1、图的基本概念2、图的存储结构2.1 邻接矩阵2.2 邻接表 3、图的遍历3.1 广度优先遍历3.2 深度优先遍历 4、最小生成树4.1 Kruskal算法4.2 Prim算法 5、最短路径5.1 单源最短路径–Dijkstra算法5.2 单源最短路径–Bellman-Ford算法5.3 多源最短路径 1、图的基本概念 …

路径规划算法:基于差分进化优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于差分进化优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于差分进化优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

nginx的rewrite功能

常用的Nginx 正则表达式 ^匹配输入字符串的起始位置$匹配输入字符串的结束位置*匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”匹配前面的字符一次或多次。如“ol”能匹配“ol”及“oll”、“olll”&#xff0c;但不能匹配“o”?匹配前面的字符零次或一次…

【动态规划专栏】--简单-- 动态规划经典题型

目录 动态规划 动态规划思维&#xff08;基础&#xff09; 状态表示&#xff08;最重要&#xff09; 状态转移方程&#xff08;最难&#xff09; 初始化&#xff08;细节&#xff09; 填表顺序&#xff08;细节&#xff09; 返回值&#xff08;结果&#xff09; 解码方…

【Python FTP/SFTP】零基础也能轻松掌握的学习路线与参考资料

一、Python FTP/SFTP的学习路线 Python FTP/SFTP是Python语言的两种常用的文件传输协议。在学习Python网络编程过程中&#xff0c;学习FTP/SFTP是非常重要的一步。下面给出Python FTP/SFTP的学习路线&#xff1a; 了解FTP/SFTP协议 在开始学习Python FTP/SFTP之前&#xff0…

LSB信息隐藏——Python实现(完整解析版)

系列文章目录 仿射密码实验-Python实现 仿射密码实验——Python实现(完整解析版) DES密码实验-C语言实现 MD5密码实验——Python实现(完整解析版) 文章目录 系列文章目录前言实验方法实验环境实验内容实验步骤1.LSB原理2.确定设计模块Lsb——embdedLsb——extract 实验结果实验…

performance_schema 初相识 配置详解 应用

千金良方&#xff1a;MySQL性能优化金字塔法则 第4章 performance_schema初相识 第5章 performance_schema配置详解 第6章 performance_schema应用示例荟萃 简介 1、实时监控Server性能监控和诊断的工具 2、它提供了丰富的性能指标和事件&#xff0c;可以帮助你深入了解 MyS…