基于C++11标准的Vector容器与多维数组编程规范学习

一、基本概念

        泛型编程:所谓泛型程序设计,就是编写不依赖于具体数据类型的程序。C++中,模板是泛型编程的主要工具。泛型程序设计的主要思想是将算法从特定的数据结构中抽象出来,使算法成为通用的、可以作用于各种不同的数据结构。以函数模板形式实现的通用算法与各种通用容器结合,提高了软件的复用性[2]。例如,所有标准库容器的迭代器都定义了==和!=,我们只要养成使用迭代器和!=的习惯,就不用太在意用的到底是哪种容器类型。

        缓冲区溢出(buffer overflow):一种严重的程序故障,主要的原因是试图通过一个越界的索引访问容器内容,容器类型包括string、vector和数组等[1]。

        容器(container):容器是容纳、包含一组元素的对象。容器类库中包含13种基本容器:向量(vector)、双端队列(deque)、列表(list)、单向链表(forward_list),数组(array),集合(set)、多重集合(multiset)、映射(map)、多重映射(multimap),以及后面四种容器的无序(unorder)形式。顺序容器(sequence container)将一组具有相同类型的元素以严格的线性形式组织起来,向量、双端队列、列表、单向链表和数组容器就属于这一种;关联容器(associative container)具有根据一组索引来快速提取元素的能力,集合和映射容器就属于这一种。而关联容器又可分为有序和无序,有序容器中键(key)按顺序存储,无序容器则使用哈希函数组织元素[2]。

        迭代器(iterator):迭代器提供了顺序访问容器中每个元素的方法,如++、--、*、->等运算符。指针也具有相同的特性,因此指针本身就是一种迭代器,迭代器是泛化的指针[2]。所有标准库容器都可以使用迭代器,但是其中只有少数几种才同时支持下标运算符。

        常量表达式(const expression):指值不会改变并且在编译过程就能得到计算结果的表达式。常量表达式有字面值、用常量表达式初始化的const对象等。

        程序的完整流程:需求分析、程序设计、代码编写(遵循良好的编码规范,确保代码的可读性、可维护性和可扩展性)、编译和构建(使用相应的编译器将源代码转换为可执行文件或库文件)、调试和测试(通过单元测试、集成测试和系统测试,验证程序在各种情况下的正确性和稳定性)、部署和运行(将程序部署到目标环境中,并根据需要提供必要的配置和资源)、优化和维护以及使用文档交付。

        范围for语句:该语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作,语法形式为:

for(declaration:expression)

        statement;

        其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量在每次迭代后会被初始化为expression部分的下一个元素值。

编程规范:

        现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针[1]。

二、auto类型说明符和decltype类型指示符

        auto类型说明符

        使用目的:编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型。auto类型说明符,可以让编译器替我们去分析表达式所属的类型。

        注意事项:编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。如,auto一般会忽略掉顶层const,同时底层const则会保留下来。

        decltype类型指示符

        使用目的希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。decltype类型指示符,可以让编译器分析表达式(如变量、函数等)并得到它的类型,却不实际计算表达式的值。

        注意事项:decltype的结果类型与表达式形式密切相关。如果decltype使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式,从而decltype就会得到引用类型。

常量符号:

        constexpr符号,既是一种类型说明符,声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化;也是C++11标准下的一种特殊的constexpr函数,这种函数足够简单以使得编译时就可以计算其结果,这样就能用constexpr函数去初始化constexpr变量。constexpr函数必须遵循①函数的返回类型及所有形参的类型都得是字面值类型;②函数体中必须有且只有一条return语句。

        注意事项:constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关(即声明类型为常量指针)。

        const限定符,定义一种值不能被改变的变量。const对象一旦创建后其值就不能再改变,所以const对象必须初始化。

        const术语:针对复杂的指针类型而言,顶层const(top-level const)表示指针本身是个常量,而用底层const(low-level const)表示指针所指的对象是一个常量。一般的话,顶层const可以表示任意的对象是常量,如算术类型、类、指针等;而底层const则与指针和引用等复合类型的基本类型部分有关。

二、编程实践

练习3.17(P94)

# include<vector>
# include<iostream>
# include<string>

using namespace std;

int main() 
{
	string word = "";
	vector<string> WordVector;
	cout << "请输入一组英文单词(单词间利用空格符间隔,EOF结尾):" << endl;
	// 将所有原始单词存入词向量中
	while (cin >> word)
	{
		WordVector.push_back(word);
	}
	cout << "单词向量构建完成!" << endl;
	// 逐单词修改为大写形式并输出(每个单词占用一行)
	// 基于范围for循环修改单词
	for (auto b = WordVector.begin(); b != WordVector.end(); ++b)
	{
		for (auto  &w : *b)
			w = toupper(w);
		cout << *b << endl;	
	}
	return 0;
}

实验结果

实验笔记[3][4]

Ⅰ cin输入流对象自动忽略空格符、制表符(Tab);

Ⅱ cin读取的是从非空白字符开始,到与目标类型不匹配的第一个字符之间的全部内容。不匹配的内容将被保存在输入缓冲流中,等待下一次输入;

Ⅲ 文件读取末尾存在EOF标识符。但是,若需要用户在控制台输入信息并模拟文件结尾符,则需要在输入信息结尾完成一系列操作(Enter换行 -> Ctrl+Z -> Enter换行)。需要注意的是,该操作限于Windows系统。

练习3.20(P94

# include<vector>
# include<iostream>

using namespace std;

int main() 
{
	int num = 0;
	vector<int> numVector;
	vector<int> biSum;
	cout << "请输入一系列整型数字串(数字与数字之间利用空格间隔,输入末尾以EOF结尾)" << endl;
	while (cin >> num)
		numVector.push_back(num);
	auto amount = numVector.size();
	auto code = amount % 2;
	auto b = numVector.begin(), e = numVector.end()-1;
	// 双指针移动
	if (amount == 0)
		cout << "整数向量未存储元素!" << endl;
	else
	{
		if (code == 1)
		{
			while (b != e)
			{
				biSum.push_back(*b + *e);
				++b;
				--e;
			}
			// 添加中间单值
			biSum.push_back(*b);
		}
		else
		{
			while (b != e - 1)
			{
				biSum.push_back(*b + *e);
				++b;
				--e;
			}
			biSum.push_back(*b + *e);
		}
	}
	// 打印计算结果
	for (auto val : biSum)
		cout << val << endl;
	return 0;
}

实验结果

实验笔记

Ⅰ size成员函数返回vector对象中元素的个数,返回值的类型是由vector定义的size_type类型(此处实验为vector<int>::size_type);

练习3.43(P116)

# include<iostream>

using namespace std;

// 所有版本直接写出数据类型
// 版本一:范围for语句管理迭代过程
void Version1(int(&array)[3][4],int row)
{
	for (int (&arr)[4] : array)
	{
		for (int a : arr)
			cout << a << " ";
		cout << endl;
	}
}

// 版本二:下标运算符
void Version2(int array[][4],int row)
{
	for (unsigned i = 0; i != row; ++i)
	{
		for (unsigned j = 0; j != 4; ++j)
			cout << array[i][j] << " ";
		cout << endl;
	}
}

// 版本三:指针
void Version3(int (*array)[4], unsigned row)
{
	for (decltype(array) arr = array; arr != array + row; ++arr)
	{
		for (int *a = *arr; a != *arr + 4; ++a)
			cout << *a << " ";
		cout << endl;
	}
}

// 版本四:auto引入
// 将二维数组的引用作为参数传递
void Version4(int (&array)[3][4],int row)
{
	for (auto &arr : array)
	{
		for (auto a : arr)
			cout << a << " ";
		cout << endl;
	}
}


int main() 
{
	int ia[3][4] = { {0,1,2,3},{4,5,6,7},{8,9,10,11} };
	cout << "Version1输出结果如下所示:" << endl;
	Version1(ia,3);
	cout << "Version2输出结果如下所示:" << endl;
	Version2(ia,3);
	cout << "Version3输出结果如下所示:" << endl;
	Version3(ia,3);
	cout << "Version4输出结果如下所示:" << endl;
	Version4(ia,3);
	return 0;
}

实验结果

实验笔记[5][6]

Ⅰ 要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型;

Ⅱ 定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。引用只能绑定在对象上,引用自身不是对象;

Ⅲ 把二维数组作为参数时,一般不指定数组第一维的大小,即使指定,也会被忽略。同时,传入的调用实参是指针,即指向固定个数容量数组的指针;

Ⅳ 如果使用数组名作函数的参数,则实参和形参都应该是数组名,且类型要相同。和普通变量作参数不同,使用数组名传递数据时,传递的是地址。

参考资料:

[1] C++ Primer中文版:第5版 /(美)李普曼(Lippman,S.B.),(美)拉乔伊(Lajoie,J.),(美)默(Moo,B.E.)著;王刚,杨巨峰译. —北京:电子工业出版社,2013.9.(第二章-变量和基本类型 /第三章-字符串、向量和数组)

[2] C++语言程序设计 / 郑莉,董渊编著.—5版.—北京:清华大学出版社,2020.11.(第十章-泛型程序设计与C++语言标准模板库)

Debug参考资料:

[3] C++ cin的使用,看这一篇就够了-CSDN博客

[4] 输入一串未知个数的数据直到EOF(-1)停止和键盘输入文件结尾符EOF_c++输入-1结束输入要怎么输-CSDN博客

[5] C++笔记 二维数组作为函数的参数详解 三种传参的方法总结 注意要点总结_二维数组作为参数传入函数-CSDN博客

[6] C++中如何将数组作为函数参数_c++ 数组作为函数参数-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 使用图片涂鸦插件

一、安装插件 npm i toast-ui/vue-image-editor npm i tui-code-snippet npm i tui-image-editor Image-editor | TOAST UI :: Make Your Web Delicious! 官网介绍说是“凭借简单和美观的完美结合&#xff0c;图像编辑器是一个功能齐全的编辑器&#xff0c;非常适合日常使…

kafka入门(四):消费者

消费者 (Consumer ) 消费者 订阅 Kafka 中的主题 (Topic) &#xff0c;并 拉取消息。 消费者群组&#xff08; Consumer Group&#xff09; 每一个消费者都有一个对应的 消费者群组。 一个群组里的消费者订阅的是同一个主题&#xff0c;每个消费者接收主题的一部分分区的消息…

基于SSM+JSP网上订餐管理系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

原来JMeter 分布式执行原理这么简单,为什么没有早点看到呢!

在使用 JMeter 进行性能测试时&#xff0c;如果并发数比较大&#xff08;比如项目需要支持 10000 并发&#xff09;&#xff0c;单台电脑&#xff08;CPU 和内存&#xff09;可能无法支持&#xff0c; 这时可以使用 JMeter 提供的分布式测试的功能&#xff0c;使用多台测试机一…

当初为什么选择计算机-希望一直干下去

还记得当初自己为什么选择计算机&#xff1f; 当初你问我为什么选择计算机&#xff0c;我笑着回答&#xff1a;“因为我梦想成为神奇的码农&#xff01;我想像编织魔法一样编写程序&#xff0c;创造出炫酷的虚拟世界&#xff01;”谁知道&#xff0c;我刚入门的那天&#xff0…

LLMs 应用程序的构建利器:LangChain 助您驰骋 AI 世界 | 开源日报 No.100

langchain-ai/langchain Stars: 67.9k License: MIT LangChain 是一个旨在通过组合性来构建 LLMs 应用程序的库。它可以帮助开发者快速将 LangChain 应用程序部署到生产环境&#xff0c;同时提供了统一的开发平台&#xff0c;用于构建、测试和监控 LLM 应用程序。该项目主要功…

Bypass open_basedir

讲解 open_basedir是php.ini中的一个配置选项&#xff0c;可用于将用户访问文件的活动范围限制在指定的区域。 假设open_basedir/var/www/html/web1/:/tmp/&#xff0c;那么通过web1访问服务器的用户就无法获取服务器上除了/var/www/html/web1/和/tmp/这两个目录以外的文件。…

【数据结构】——排序篇(下)

前言&#xff1a;前面我们的排序已经详细的讲解了一系列的方法&#xff0c;那么我们现在久之后一个归并排序了&#xff0c;所以我们现在就来讲解一下归并排序。 归并排序&#xff1a; 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法…

分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测

分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测 目录 分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类…

Kubernetes -Kubernetes中的Network组件

Network是Kubernetes体系中的重头戏&#xff0c;相比于其它组件来说也比较难&#xff0c;因为Kubernetes中所有的Pod或者服务之间一定是需要进行网络通信的&#xff0c;如果不能解决网络通信的问题&#xff0c;那可以说整个Kubernetes体系中的Pod是没有灵魂的。 所以必须要把N…

dlib是什么?

dlib C Libraryhttp://dlib.net/ dlib是什么&#xff1f; Dlib is a modern C toolkit containing machine learning algorithms and tools for creating complex software in C to solve real world problems. It is used in both industry and academia in a wide range of…

面试官:性能测试瓶颈调优你是真的会吗?

引言&#xff1a;性能瓶颈调优 在实际的性能测试中&#xff0c;会遇到各种各样的问题&#xff0c;比如 TPS 压不上去等&#xff0c;导致这种现象的原因有很多&#xff0c;测试人员应配合开发人员进行分析&#xff0c;尽快找出瓶颈所在。 理想的性能测试指标结果可能不是很高&…

小目标检测模型设计的一点思考

1. 小目标的特性 目标之间的交叠概率比较低&#xff0c;即使有交叠&#xff0c;其IoU多数情况下也是比较小的 AI-TOD Tiny Person Dateset 小目标自身的纹理显著度有强弱区别&#xff0c;但是总体来说纹理特征都较弱&#xff0c;很多时候需要借助一定的图像上下文来帮助确认 …

SpringBoot 官方脚手架不再支持Java8和Java11

Spring 官方脚手架不再支持初始化 Java8 和 Java 11 项目&#xff0c;目前仅支持初始化Java17 和 Java21 项目。 阿里巴巴Spring脚手架支持初始化Java8、Java11、Java17、Java19 的项目&#xff0c;不支持初始化Java21的项目。

一文搞懂Lombok Plugins使用与原理

目录 一文搞懂Lombok使用与原理 1.前言2.什么是Lombok3. IntelliJ安装Lombok3.1通过IntelliJ的插件中心安装3.2在项目中使用Lombok Plugins 4.Lombok 注解大全说明4.1POJO类常用注解4.2其他注解 5.Lombok常见问题6.总结7.参考 文章所属专区 超链接 1.前言 2.什么是Lombok Lo…

WPS宏批量修改图片尺寸

致谢 感谢网络各位大佬的分享&#xff0c;可以让我快速的学习这块内容。 JS宏代码

上班必备——项目部署环境

大家都知道&#xff0c;互联网行业有很多的岗位&#xff0c;前端&#xff0c;后端&#xff0c;产品&#xff0c;测试&#xff0c;ui等。 ui&#xff0c;产品和测试的同事在前端开发的过程中&#xff0c;都会时刻关注着进度&#xff0c;是要看页面效果的&#xff0c;这个时候怎…

MIT线性代数笔记-第28讲-正定矩阵,最小值

目录 28.正定矩阵&#xff0c;最小值打赏 28.正定矩阵&#xff0c;最小值 首先正定矩阵是一个实对称矩阵 由第 26 26 26讲的末尾可知正定矩阵有以下四种判定条件&#xff1a; 所有特征值都为正左上角所有 k k k阶子矩阵行列式都为正&#xff08; 1 ≤ k ≤ n 1 \le k \le n …

SpringBoot默认使用CGLIB的原因

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

基于ssm农产品仓库管理系统系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本农产品仓库管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…
最新文章