(学习总结15)C++11小语法与拷贝问题

news2024/12/23 14:52:05

C++11小语法与拷贝问题

  • auto关键字
  • 范围for
  • initializer_list
  • 深拷贝与浅拷贝
  • 写时拷贝

以下代码环境为 VS2022 C++。

auto关键字

在早期 C/C++ 中 auto 的含义是:使用 auto 修饰的变量,是具有自动存储器的局部变量,不过一般都会隐藏,导致后来不重要了。C++11中,标准委员会赋予了 auto 全新的含义,即:auto 不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto 声明的变量必须由编译器在编译时期推导而得。

  1. 用 auto 声明指针类型时,用 auto 和 auto* 没有任何区别。

  2. 用 auto 声明引用类型时则必须加 &。

  3. 当在同一行用 auto 声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

  4. auto 不能作为函数的参数,但可以做返回值,不过建议谨慎使用。

  5. auto 不能直接用来声明数组。

#include <iostream>

void test1()
{
	// auto 声明的变量必须初始化,否则报错
	//auto one;
	
	// 以下变量类型由编译器在编译时期推导而得
	auto a = 10;
	auto b = 'C';
	auto c = 1.5;

	// 1.用 auto 声明指针类型,auto 和 auto* 两者没有区别
	auto d = &a;
	auto* e = &a;

	// 2.auto 声明引用类型需要加上 &
	auto& f = a;

	// 3.同一行用 auto 声明多个变量,必须是相同的类型,不然报错
	//auto g = 1, h = 'c', i = 2.5;
	auto j = 1, k = 2, l = 3;

	// 5.auto不能直接用来声明数组,但可声明指针去修改
	//auto m[10] = { 0 };
	//auto n[] = { 1, 2, 3 };
	int arr[] = { 1, 2, 3 };
	auto o = arr;	
	o[0] = 5;
	o[1] = 6;
}

// 4.auto 不能作为函数的参数,
//void test2(auto number)
//{
//	;
//}

// 但可以做返回值,不过建议谨慎使用
auto test3()
{
	return 0;
}

int main()
{
	test1();

	return 0;
}

范围for

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此 C++11 中引入了基于范围的 for 循环。for 循环后的括号由冒号 “ : ” 分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围 for 可以作用到数组和容器对象上进行遍历,范围 for 的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

#include <iostream>
#include <vector>
#include <list>

void test1()
{
	int arr1[] = { 1, 2, 3, 4, 5 };
	std::vector<int> arr2 = { 5, 4, 3, 2, 1 };
	std::list<int> arr3 = { 1, 3, 5, 7, 9 };

	// 一般遍历
	int len1 = sizeof(arr1) / sizeof(arr1[0]);
	for (int i = 0; i < len1; ++i)
	{
		std::cout << arr1[i] << " ";
	}
	std::cout << std::endl;

	std::vector<int>::iterator it1 = arr2.begin();
	while (it1 != arr2.end())
	{
		std::cout << *it1 << " ";

		++it1;
	}
	std::cout << std::endl;

	std::list<int>::iterator it2 = arr3.begin();
	while (it2 != arr3.end())
	{
		std::cout << *it2 << " ";

		++it2;
	}
	std::cout << std::endl;

	std::cout << "---------" << std::endl;

	// 范围for本质是替换为迭代器遍历,
	// 只要能用迭代器遍历的容器都能使用范围for
	for (const auto& e : arr1)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;

	for (const auto& e : arr2)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;

	for (const auto& e : arr3)
	{
		std::cout << e << " ";
	}
	std::cout << std::endl;
}

int main()
{
	test1();

	return 0;
}

initializer_list

为了使 C++ STL 中的容器支持与数组一样的使用 " { 数据1, 数据2… } " 初始化,在 C++11 引入了 initializer_list 类。

// 数组使用 { } 初始化
int arr1[5] = { 1, 2, 3, 4, 5 };	
int arr2[] = { 5, 4, 3, 2, 1 };

详细可参考:std::initializer_list

" { } " 内的数据是在栈上开辟存储的,而 initializer_list 类里封装有两个指针,一个指向 " { } " 第一个元素,另一个指向最后一个元素下一个位置,在 VS2022 调试时可以看到:
在这里插入图片描述
并且其中所有元素都加上了 const,表示 " 只读 ",无法修改。

因此使用 C++ STL 的容器初始化时,在 initializer_list 类的基础上可以使用 { } 初始化:

#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <map>
#include <set>

void test1()
{
	std::vector<int> 	arr1 = { 1, 2, 3, 4, 5 };
	std::list<int> 		arr2 = { 1, 2, 3, 4, 5 };
	std::string 		arr3 = { 'a', 'b', 'c', 'd', '\0' };
	std::deque<int> 	arr4 = { 1, 2, 3, 4, 5 };
	std::map<int, char> arr5 = {{1, 'a'}, {2, 'b'}, {3, 'c'}, {4, 'd'}, {5, 'e'}};
	std::set<int> 		arr6 = { 1, 2, 3, 4, 5 };
}

int main()
{
	test1();

	return 0;
}

若要使自己的容器也能支持 " { } " 方式初始化,需要在类中单独添加一个为 initializer_list 类准备的构造函数。

这里以这篇博客为例:(C++ STL)vector类的简单模拟实现与源码展示

在类中增加以 initializer_list 类参数的构造函数即可:

template<class Type>					// 若类中已经有代表类型的关键字,
vector(std::initializer_list<Type> il)	// 可去掉 template<class Type> 和
{										// 替换 std::initializer_list<Type> 中的 Type
    for (const auto& e : il)			// initializer_list 支持迭代器访问
    {
        push_back(e);					// my::vector<T> 的成员函数
    }
}

深拷贝与浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。
在这里插入图片描述

可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。
在这里插入图片描述
如果 C++ 一个类中涉及到资源的管理,其 拷贝构造函数赋值运算符重载 以及 析构函数 必须要显式给出。一般情况都是按照深拷贝方式提供。

写时拷贝

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成 1,每增加一个对象使用该资源,就给计数增加 1,当某个对象被销毁时,先给该计数减 1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

具体细节可参考这位大佬的文章:
C++ STL string的Copy-On-Write技术
C++的std::string的“读时也拷贝”技术!

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

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

相关文章

科研绘图 - Python - 柱状图代码及展示

1 import pandas as pd import matplotlib.pyplot as pltstudents pd.read_excel(./Students.xlsx)print(----原始数据----) print(students)students.sort_values(by2017,inplaceTrue,ascendingFalse) students.plot.bar(xField,y[2016,2017],color[orange,red])plt.title(I…

【Redis】Redis 客户端开发与 Java 集成:RESP协议解析与实战操作

目录 客⼾端Redis Java使⽤ 样例列表引⼊依赖配置端⼝转发连接 Redis Server基础操作字符串操作列表操作哈希表操作集合操作有序集合操作访问集群 Redis Java 集成到 Spring Boot使⽤ Spring Boot 连接 Redis 单机创建项⽬配置 redis 服务地址创建 Controller使⽤ String使⽤ L…

华为OD机试真题 - 分割均衡字符串 - 贪心算法(Python/JS/C/C++ 2024 D卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、…

集成电路学习:什么是GPIO通用输入输出

GPIO&#xff1a;通用输入输出 GPIO&#xff0c;全称General Purpose Input/Output&#xff0c;即通用输入/输出端口&#xff0c;是嵌入式系统中非常重要的基本硬件资源之一。以下是对GPIO的详细解析&#xff1a; 一、GPIO的定义与功能 GPIO是一种非常灵活的接口&#xff0c;可…

ping不通本地虚拟机的静态ip的解决方案

找到网络配置文件 一般我们设置虚拟机文件为静态IP地址&#xff0c; 比如 /etc/sysconfig/network-scripts/ifcfg-ens33 记住Gateway 192.168.200.2 查看虚拟网络编辑器 把子网ip改为192.168.200.0 前三部分相同&#xff0c;第四部分是0 把nat设置中的网关ip改成Gateway 1…

时空图卷积网络:用于交通流量预测的深度学习框架-1

摘要 准确的交通预测对于城市交通控制和引导至关重要。由于交通流的高度非线性和复杂性&#xff0c;传统方法无法满足中长期预测任务的需求&#xff0c;且往往忽略了空间和时间的依赖关系。本文提出一种新的深度学习框架——时空图卷积网络(STGCN)来解决交通领域的时间序列预测…

「MyBatis」图书管理系统 v1.0

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;JavaEE &#x1f387;欢迎点赞收藏加关注哦&#xff01; 图书管理系统 v1.0 &#x1f349;登录&#x1f349;图书操作&#x1f34c;图书类&#x1f34c;页面信息&#x1f34c;操作 &#x1f34…

Java中的经典排序算法:快速排序、归并排序和计数排序详解(如果想知道Java中有关快速排序、归并排序和计数排序的知识点,那么只看这一篇就足够了!)

前言&#xff1a;排序算法在计算机科学中占有重要地位&#xff0c;不同的算法适用于不同的场景。本文将深入探讨快速排序、归并排序和计数排序。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 先让我们看一下本文大致的讲解内…

新生在线分班查询,用这个小程序制作仅需一分钟!

今天许多学校已陆续开学&#xff0c;老师们又开始忙碌起来。他们需要将新生的分班信息逐一通知给每位家长&#xff0c;这不仅是一项繁琐的工作&#xff0c;而且效率也不高。传统的方法是通过电话、短信或邮件一一通知&#xff0c;这不仅耗时耗力&#xff0c;还容易出现信息传递…

百度文库文章-暂存下-------题 目: 链式简单选择排序

题 目: 链式简单选择排序 初始条件&#xff1a; 理论&#xff1a;学习了《数据结构》课程&#xff0c;掌握了基本的数据结构和常用的算法&#xff1b; 实践&#xff1a;计算机技术系实验室提供计算机及软件开发环境。 要求完成的主要任务: &#xff08;包括课程设计工作量…

如何用pytorch进行图像分类

如何用pytorch进行图像分类 使用PyTorch进行图像分类是深度学习中的一个常见任务&#xff0c;涉及一系列步骤&#xff0c;从数据预处理到模型训练和评估。下面将详细描述每个步骤&#xff0c;从零开始构建一个图像分类器。 1. 安装必要的库 在开始之前&#xff0c;首先需要确…

驱动(RK3588S)第四课时:模块化编程

目录 一、什么是模块化编程二、怎么把自己编译代码给加载到开发板上运行三、驱动编程的框架四、驱动编程具体实例1、编写单模块化驱动代码2、编写多模块化驱动代码3、编写向模块传参驱动代码4、编写多模块化驱动代码另一种方式 一、什么是模块化编程 在嵌入式里所谓的模块化编…

Vue——day07之条件渲染、列表渲染以及监测数据

目录 1.template标签 2.条件渲染 3.列表渲染 4.v-for中的key的作用以及原理 5.列表过滤 placeholder 前端空字符串 使用数据监视watch实现 使用计算属性实现 6.列表排序 7.Vue更新数据检测失败 原因 总结 1.template标签 template标签是Vue.js中的一个特殊元素&am…

kube-scheduler调度策略之预选策略(三)

一、概述 摘要&#xff1a;本文我们继续分析源码&#xff0c;并聚焦在预选策略的调度过程的执行。 二、正文 说明&#xff1a;基于 kubernetes v1.12.0 源码分析 上文我们说的(g *genericScheduler) Schedule()函数调用了findNodesThatFit()执行预选策略。 2.1 findNodesTha…

Truncated incorrect max_connections value: ‘999999‘

MySQL 的最大连接数&#xff08;max_connections&#xff09;可以设置的上限值在不同的资料中有所不同。以下是一些关键信息&#xff1a; 默认值和默认范围&#xff1a; MySQL 的默认最大连接数通常为 100 。一些资料提到默认值为 151 。 最大允许值&#xff1a; MySQL 的最大…

ant-design-vue:a-table表格中插入自定义按钮

本文将介绍如何使用ant-design-vue在a-table表格中加入自定义按钮和图标的代码。 结果如下图所示&#xff0c; 一、简单示例 <template><a-table:columns"columns":data-source"data":row-selection"rowSelection":ellipsis"tru…

对称密码学

1. 使用OpenSSL 命令行 在 Ubuntu Linux Distribution (发行版&#xff09;中&#xff0c; OpenSSL 通常可用。当然&#xff0c;如果不可用的话&#xff0c;也可以使用下以下命令安装 OpenSSL: $ sudo apt-get install openssl 安装完后可以使用以下命令检查 OpenSSL 版本&am…

深度学习基础案例4--构建CNN卷积神经网络实现对猴痘病的识别(测试集准确率86.5%)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 下一周会很忙&#xff0c;更新可能不及时&#xff0c;请大家见谅这个项目我感觉是一个很好的入门案例&#xff0c;但是自己测试的时候测试集准确率只比较…

mcu loader升级固件原理与实现

1 mcu loader升级固件原理 mcu 固件有两部分&#xff0c;如下图所示&#xff0c;一部分是 loader.bin&#xff0c;一部分是 app.bin&#xff0c;将两部分的固件合并在一起烧录进 mcu 的 flash 当中。mcu 上电进入loader 模式执行 loader.bin 部分的程序&#xff0c;然后读取 fl…

前端踩坑记录:javaScript复制对象和数组,不能简单地使用赋值运算

问题 如图&#xff0c;编辑table中某行的信息&#xff0c;发现在编辑框中修改名称的时候&#xff0c;表格中的信息同步更新。。。 检查原因 编辑页面打开时&#xff0c;需要读取选中行的信息&#xff0c;并在页面中回显。代码中直接将当前行的数据对象赋值给编辑框中的表单对…