【C++】c++ 11

news2024/9/20 18:37:11

目录

前言

列表初始化

std::initializer_list

右值引用和移动拷贝

左值和右值

左值引用和右值引用的区别

万能引用(引用折叠)

完美转发

默认成员函数控制


列表初始化

C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。比如:

//也算是兼容C
struct Point
{
	int _x;
	int _y;
};
int main()
{
	int array1[] = { 1, 2, 3, 4, 5 };
	int array2[5] = { 0 };
	Point p = { 1, 2 };
	return 0;
}

C++11扩大了{ }(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加

struct Point
{
	int _x;
	int _y;
};
int main()
{
	int x1 = 1;
	int x2{ 2 };
	int array1[]{ 1, 2, 3, 4, 5 };
	int array2[5]{ 0 };
	Point p{ 1, 2 };
	// C++11中列表初始化也可以适用于new表达式中
	int* pa = new int[4] { 0 };
	return 0;
}

创建对象时也可以使用列表初始化方式调用构造函数初始化:

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2022, 1, 1); // old style

	// C++11支持的列表初始化,下面两个会调用构造函数初始化
	Date d2{ 2022, 1, 2 };
	Date d3 = { 2022, 1, 3 };
	return 0;
}
std::initializer_list

initializer_list是C++11新增加的容器,底层就是一个数组。

int main()
{
	//这里初始化其实是构造初始化,先不在意底层
	initializer_list<int> l = {0, 1, 2, 34};
	initializer_list<int>::iterator it = l.begin();
	while (it != l.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

initializer_list平常并无作用,但是C++11对{}有特殊处理,它真正的应用场景是用于构造其它容器

//C++11为vector、map等容器都提供了initializer_list做参数的构造
//原理也很简单,先将{}转变成initializer_list,然后遍历initializer_list尾插即可
int main()
{
	vector<int> v = { 0, 1, 2, 3, 4, 5 };
	for (auto e : v) cout << e << " ";
	cout << endl;

	map<int, int> m = { {0, 1}, {1, 0}, {10, 9} };
	for (auto kv : m)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

右值引用和移动拷贝

左值和右值

首先先分清什么是左值,什么是右值——不是在=左边的就叫左值,在=右边的就叫右值

左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。

最显著的特点就是左值可以被取地址,右值不能被取地址(是否真的存储)

左值引用就是给左值的引用,给左值取别名。

// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;

右值不能被取地址,例如字面常量、表达式返回值,函数返回值(左值引用返回不是右值,传值返回才是右值)

右值引用就是对右值的引用,给右值取别名

// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);

左值引用和右值引用的区别

1.左值引用只能引用左值,不能引用右值;右值引用同理

2.const 左值引用可以引用左值也可以引用右值,但是反过来就不行

3.右值引用可以引用move后的左值

左值引用的使用场景: 做参数和做返回值都可以提高效率

为什么要有右值引用呢,主要是为了弥补左值引用的不足

场景:当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回, 只能传值返回。

例如:zzb::string to_string(int value)函数中可以看到,这里只能使用传值返回,传引用返回当该函数栈帧被销毁的时候该位置有可能被其他变量所占用,存在很大的问题,但是传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造),效率很低

zzb::string to_string(int x)
	{
		bit::string ret;
		while (x)
		{
			int val = x % 10;
			x /= 10;
			ret += ('0' + val);
		}

内置类型的右值叫做纯右值,将自定义的右值称为将亡值

我们先来看下面这两种情况

int main()
{
	bit::string s1 = bit::to_string(1234);

	bit::string s2;
	s2 = bit::to_string(2345);
	return 0;
}

下面的那个:

str拷贝给临时对象,临时对象拷贝构造给ret2

自定义创建时调用一次构造函数

函数栈帧销毁的时候,创建临时对象的时候调用拷贝构造

返回值作为右值给左值赋值的时候又调用拷贝构造

 上面的减少的一次可以理解为没有产生临时对象了,直接赋值给ret2,这时编译器优化后的结果

老一点的编译器可能没有这样优化

如果是浅拷贝的类那还没事,但如果是深拷贝的类,短短一个赋值操作就要深拷贝三次,代价太大了,反正这个函数栈帧里的空间都要被销毁的,如果把它拿过来直接用的话,是不是就很方便了

所以就有了移动构造和移动赋值,这时候右值引用的价值就体现出来了,可以区分左值和右值了

如果参数传的是将亡值,则直接将资源交换,不仅减少了拷贝,还将不要的资源转移到了即将要销毁的空间,过后自动销毁,一举两得

移动构造——不用开辟空间,直接交换得到目标值,目标即将被销毁的时候使用

右值引用是间接起作用的,对深拷贝的类有意义

左值引用是直接起作用,传引用返回

右值被右值引用后的属性是左值

右值不能修改,但是被右值引用之后需要被修改——>属性变成左值(不能修改怎么转移资源,也就无法实现移动构造和移动拷贝)

万能引用(引用折叠)

函数模板下才有用!

 可以接受左值和右值,左值的时候就相当于将两个&折叠成一个,所以也叫引用折叠

完美转发

按照上面的写法写即可

可以保持原有属性(右值被右值引用后属性变成左值)

默认成员函数控制

这里为什么条件那么严格呢?

其实这三个一般都是绑定在一起的,因为写了析构一般都设计深拷贝,所以也就要自己写拷贝构造和拷贝赋值,不然会出现问题

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

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

相关文章

Gartner 成熟度曲线报告解读(一)| 2024中国IT基础设施使用趋势、影响中国IT使用的4大因素

近些年&#xff0c;面对数字化转型、信息化发展、政策监管与地缘政治等外部因素&#xff0c;以及降本增效的内部需求&#xff0c;不少中国企业在制定 IT 基础设施发展策略时遇到多重挑战。为帮助国内企业用户优化基础设施战略&#xff0c;Gartner 近日发布《中国 IT 基础设施技…

【HCIA-Datacom】华为VRP系统

| &#x1f449;个人主页&#xff1a;Reuuse 希望各位多多支持&#xff01;❀ | &#x1f449;往期博客&#xff1a;网络参考模型 | 最后如果对你们有帮助的话希望有一个大大的赞&#xff01; | ⭐你们的支持是我最大的动力&#xff01;⭐ | 目录 1. 华为VRP系统概述VRP概念设备…

Docker-compose:管理多个容器

Docker-Compose 是 Docker 公司推出的一个开源工具软件&#xff0c;可以管理多个 Docker 容器组成一个应用。用户需要定义一个 YAML 格式的配置文件 docker-compose.yml&#xff0c;写好多个容器之间的调用关系。然后&#xff0c;只要一个命令&#xff0c;就能同时启动/关闭这些…

七、垃圾收集器ParNewCMS与底层三色标记算法详解

文章目录 垃圾收集算法分代收集理论标记-复制算法标记-清除算法标记-整理算法 垃圾收集器1.1 Serial收集器(-XX:UseSerialGC -XX:UseSerialOldGC)1.2 Parallel Scavenge收集器(-XX:UseParallelGC(年轻代),-XX:UseParallelOldGC(老年代))1.3 ParNew收集器(-XX:UseParNewGC)1.4 C…

POSIX信号量以及利用POSIX信号量实现基于循环队列的高效生产者消费者模型

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f341;POSIX信号量 &#x1f341;信号量的相关接口介绍*初始化信号量**销毁信号量**等待信号量**发布信号量* &#x1f341;&…

YOLOv9 简介

YOLO v9 是目前表现最佳的目标检测器之一&#xff0c;被视为现有 YOLO 变体&#xff08;如 YOLO v5、YOLOX 和 YOLO v8&#xff09;的改进版本。 YOLOv9 在实时目标检测领域取得了重大进展&#xff0c;引入了诸如可编程梯度信息&#xff08;PGI&#xff09;和通用高效层聚合网…

后端开发刷题 | 打家劫舍

描述 你是一个经验丰富的小偷&#xff0c;准备偷沿街的一排房间&#xff0c;每个房间都存有一定的现金&#xff0c;为了防止被发现&#xff0c;你不能偷相邻的两家&#xff0c;即&#xff0c;如果偷了第一家&#xff0c;就不能再偷第二家&#xff1b;如果偷了第二家&#xff0…

Dina靶机详解

靶机下载 https://www.vulnhub.com/entry/dina-101,200/ 靶机配置 默认是桥接模式&#xff0c;切换为NAT模式后重启靶机 主机发现 arp-scan -l 端口扫描 nmap -sV -A -T4 192.168.229.157 发现80端口开启&#xff0c;访问 访问网站 目录扫描 python dirsearch.py -u http…

1.2 交换技术

欢迎大家订阅【计算机网络】学习专栏&#xff0c;开启你的计算机网络学习之旅&#xff01; 文章目录 前言一、电路交换1. 定义与原理2. 工作过程3. 优点与局限 二、分组交换1. 定义与原理2. 工作过程3. 优点与局限 三、报文交换1. 定义与原理2. 工作过程3. 优点与局限 四、比较…

改进RRT*的路径规划算法

一、RRT算法 RRT 算法是一种基于随机采样的快速搜索算法。该算法的主要思想是通过随机采样来创建一个快速探索的树&#xff0c;从而生长出一条从起点到终点的路径。如图为随机树的生长过程。 初始化。首先&#xff0c;初始化起始点和目标点位置&#xff0c;并将起点作为根节点…

printf()函数的全面介绍及用法——简单易懂

printf&#xff08;&#xff09;函数介绍 目录 printf&#xff08;&#xff09;函数介绍 一&#xff1a;头文件 二&#xff1a;格式控制字符串 1.格式字符。 2.转义字符。 3.普通字符。 三&#xff1a;格式字符输出示例 1. %c-----------输出字符 2. %s-----------输…

Linux中断实操-概念

1、裸机中的中断处理方法&#xff1a; &#xff08;1&#xff09;使能中断、初始化相应寄存器 &#xff08;2&#xff09;注册中断服务函数&#xff0c;向irqTable数组的指定标号处写入中断服务函数 &#xff08;3&#xff09;中断发生后进入IRQ中断服务函数&#xff0c;执行对…

【0~1】实现一个精简版的Tomcat服务器

真正的勇气&#xff0c;是在知道生活的真相之后&#xff0c;依然热爱生活。 《To Kill a Mockingbird》 01 Tomcat 介绍 Tomcat 是一个开源的 Java 应用服务器&#xff0c;主要用来运行基于 Servlet 和 JSP 技术的 Web 应用。Tomcat 实现了 Servlet 规范和 JSP 规范&#xff0…

一次RPC调用过程是怎么样的?

注册中心 RPC&#xff08;Remote Procedure Call&#xff09;翻译成中文就是 {远程过程调用}。RPC 框架起到的作用就是为了实现&#xff0c;调用远程方法时&#xff0c;能够做到和调用本地方法一样&#xff0c;让开发人员更专注于业务开发&#xff0c;不用去考虑网络编程等细节…

【开源免费】基于SpringBoot+Vue.JS企业客户管理系统(JAVA毕业设计)

本文项目编号 T 036 &#xff0c;文末自助获取源码 \color{red}{T036&#xff0c;文末自助获取源码} T036&#xff0c;文末自助获取源码 目录 一、系统介绍1.1 管理员角色1.2 普通员工角色1.3 系统特点 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内…

苹果手机备份照片怎么删除

在数字时代&#xff0c;备份照片是保护我们珍贵记忆不受意外丢失影响的一种重要方式。苹果手机用户通常利用iCloud或iTunes来备份他们的照片&#xff0c;确保数据的安全。然而&#xff0c;随着时间的推移&#xff0c;这些备份可能会积累大量不再需要的照片&#xff0c;占用宝贵…

鸿蒙开发之ArkTS 基础二

ArkTS常用的基础数据类型 1.字符串 关键字是string 2.数字 关键字是number 3.布尔 关键字是boolean 语法格式是:let 变量名:变量类型 变量值 其中let是关键表示变量&#xff0c;可以修改&#xff0c;可以改变一只对应的是const 修饰&#xff0c;常量不能修改&#xff0c;…

Python画笔案例-050 绘制天空之眼

1、绘制天空之眼 通过 python 的turtle 库绘制 天空之眼&#xff0c;如下图&#xff1a; 2、实现代码 绘制 天空之眼&#xff0c;以下为实现代码&#xff1a; """天空之眼.py """ import math import turtledef draw_square(length,level):if l…

idea同时装了两个版本,每次打开低版本都需要重新激活破解

问题描述&#xff1a; idea同时装了两个版本&#xff0c;每次打开低版本都需要重新激活破解。低版本是2021.1&#xff0c;高版本是2023.1 解决方案&#xff1a; 找到idea的配置路径&#xff0c;比如我的是&#xff1a;C:\Users\Administrator\AppData\Roaming\JetBrains 2021…

【我要成为配环境高手】Nodejs安装与配置

文章目录 1.nodejs安装2.配置npm的全局安装路径3.切换npm的淘宝镜像4.安装vue-cli 1.nodejs安装 从官网下载安装LTS版本的nodejs nodejs会自动安装环境变量&#xff0c;因此安装完成后直接在cmd中查看node版本 node -v2.配置npm的全局安装路径 以管理员身份运行cmd&#xff…