C++和标准库速成(五)——C风格的数组、std::array、std::vector、std::pair和std::optional

目录

  • 1. C风格的数组(不建议)
    • 1.1 初始化
    • 1.2 获取数组大小
    • 1.3 多维数组
  • 2. std::array(C++11)
  • 3. std::vector
  • 4. std::pair
  • 5. std::optional(C++17)
  • 参考

1. C风格的数组(不建议)

1.1 初始化

  数组具有一系列的值,所有值的类型相同,每个值可根据它在数组中的位置进行访问。在C++中声明数组时,必须声明数组的大小。数组的大小不能用变量表示——必须用常量或常量表达式表示数组大小。在下面的代码中,首先声明了具有3个整数的数组,之后的三行语句将每个元素初始化为0。

int myArray[3];
myArray[0] = 0;
myArray[1] = 0;
myArray[2] = 0;

  警告:在C++中,数组的第一个元素始终在位置0,而非位置1!数组的最后一个元素的位置始终是数组大小减1。
  使用循环可初始化每个元素。但不使用循环或前面的初始化机制,也可以使用如下的单行代码完成零初始化的操作。
  int myArray[3] = { 0 };
  甚至可以省略0,如下所示:
  int myArray[3] = {};
  最后,等号也是可选的,所以可以写出如下所示的代码:
  int myArray[3] {};
  数组也可以用初始化列表初始化,此时编译器可自动推断数组的大小。例如:
  int myArray[] { 1, 2, 3, 4 }; // the compiler creates an array of 4 elements.
  如果指定了数组的大小,而初始化列表包含的元素数量少于给定大小,则将其余元素设置为0。例如,以下代码仅将数组中的第一个元素设置为2,将其余元素设置为0.
  int myArray[3] { 2 };

1.2 获取数组大小

  要获取基于栈的C风格数组的大小,可使用std::size()函数,在<array>中。它返回size_t类型,这是定义在<cstddef>中定义的无符号整数类型。示例如下:
  std::size_t arraySize { std::size(myArray) };
  获取基于栈的C风格数组的大小的一个更老的技巧是使用sizeof运算符。sizeof运算符返回其参数的大小,以字节为单位。要获取基于栈的数组中的元素数,可以将数组的大小除以第一个元素的大小。示例如下:
  std::size_t arraySize { sizeof(myArray) / sizeof(myArray[0]) };

1.3 多维数组

  前面的代码展示了一个一维数组,可将其当作一行整数,每个数字都具有自己的编号。C++允许使用多维数组,可将二维数组看成棋盘,每个位置都具有x坐标值和y坐标值。三维数组和更高维的数组更难描绘,也极少使用。下面的代码展示了用于井字游戏棋盘的二维字符数组,然后在位于中央的方块中填充一个o。

char ticTacToeBoard[3][3];
ticTacToeBoard[1][1] = 'o';

  下面展示了这个棋盘的图像表示,并给出了每个方块的位置。

ticTacToeBoard[0][0]ticTacToeBoard[0][1]ticTacToeBoard[0][2]
ticTacToeBoard[1][0]ticTacToeBoard[1][1]ticTacToeBoard[1][2]
ticTacToeBoard[2][0]ticTacToeBoard[2][1]ticTacToeBoard[2][2]

  警告:在C++中,最好避免使用C风格数组,改用标准库功能,如std::array和std::vector。

2. std::array(C++11)

  C++中有一种固定大小的特殊容器std::array,这种容器在<array>头文件中定义。它基本上是对C风格的数组进行了简单的包装。用std::array替代C风格数组会带来很多好处:它总是知道自身大小;不会自动转换为指针,从而避免了某些类型的bug;具有迭代器,可方便地遍历元素。
  下面展示了array容器的用法。在array<int, 3>中,第一个参数表示数组中元素的类型,第二个参数表示数组的大小。

std::array<int, 3> arr { 9, 8, 7 };
std::cout << std::format("Array size = {}\n", arr.size());
std::cout << std::format("2nd element = {}\n", arr[1]);

  C++支持所谓的类模板参数推导CTAD,这可以避免为某些类模板指定尖括号之间的模板类型。CTAD仅在初始化时起作用,因为编译器使用此初始化自动推导模板类型。这适用于std::array,允许你按以下方式定义以前的数组:
  std::array arr { 9, 8, 7 };
  注意:C风格数组和std::array都具有固定的大小,在运行时数组不会增大或缩小。
  如果希望数组的大小是动态的,推荐使用std::vector。

3. std::vector

  标准库提供了多个不同的非固定大小容器,用于存储信息。std::vector就是此类容器的一个示例,它在<vector>中声明,用一种更灵活和安全的机制取代C风格数组的概念。用户不需要担心内存的管理,因为vector将自动分配足够的内存来存放其元素。vector是动态的,意味着可在运行时添加和删除元素。示例如下:

// create a vector of integers.
std::vector<int> myVector { 11, 22 };// add some more integers to the vector using push_back().
myVector.push_back(33);
myVector.push_back(44);// access elements.
std::cout << std.format("1st element: {}\n", myVector[0]);

  myVector被声明为std::vector<int>,尖括号用来指定模板参数。vector是一个泛型容器,几乎可以容纳任何类型的对象,但是vector中的所有元素必须是同一类型,在尖括号内指定这个类型。
  与std::array相同,vector类模板支持CTAD,允许你按下列方式定义myVector:
  std::vector myVector { 11, 22 };
  再次说明,需要初始化器才能使CTAD正常工作,下面是非法的
  std::vector myVector;
  为向vector中添加元素,可使用push_back()方法。可使用类似于数组的语法访问各个元素。

4. std::pair

  std::pair定义在<utility>中。它将两个可能不同类型的值组合在一起,可通过first和second公共数据成员访问这些值。示例如下:

std::pair<double, int> myPair { 1.23, 5 };
std::cout << std::format("{} {}\n", myPair.first, myPair.second);

  pair也支持CTAD,所以你可以按下列方式定义myPair:
  std::pair myPair { 1.23, 5 };

5. std::optional(C++17)

  在<optional>中定义的std::optional保留特定类型的值,或者不包含任何值。基本上,想要允许值是可选的,则可以将optional用于函数的参数。如果函数可能返回也可以不返回某些内容,则通常也将optional作为函数的返回类型。这消除了从函数中返回特殊值的需要,如nullptr、end()、-1、EOF之类的。它还消除了将函数编写为返回代表成功或失败的布尔值的需要,同时将函数的实际结果存储在作为输出参数传递给函数的实参中。
  optional类型是一个类模板,因此必须在尖括号之间指定所需的实际类型,如std::optional<int>。示例如下:

std::optional<int> getData(bool giveIt) {if ( giveIt ) {return 42;}return std::nullopt; // or simply return {};
}

  可以按下列方式调用这个函数:

std::optional<int> data1 { getData(true) };
std::optional<int> data2 { getData(false) };

  可以用has_value()方法判断一个optional是否有值,或简单地将optional用在if语句中。

std::cout << std::format("data1.has_value = {}\n", data1.has_value());
if ( data2 ) {std::cout << "data2 has a value.\n";
}

  如果optional有值,可以使用value()或解引用运算符访问它。

std::cout << std::format("data1.value = {}\n", data1.value());
std::cout << std::format("data1.value = {}\n", *data1);

  如果你对一个空的optional使用value(),将会抛出std::bad_optional_access异常。
  value_or()可以用来返回optional的值,如果optional为空,则返回指定的值。

std::cout << std::format("data2.value = {}\n", data2.value_or(0));

  注意:不能将引用保存在optional中,所以optional<T&>是无效的。但是可以将指针保存在optional中。

参考

[比] 马克·格雷戈勒著 程序喵大人 惠惠 墨梵 译 C++20高级编程(第五版)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# MVC项目部署II后错误,403禁止访问:访问被拒绝问题处理

C# MVC项目部署II后错误&#xff0c;403禁止访问&#xff1a;访问被拒绝问题处理 问题如下&#xff1a; 解决办法&#xff1a; 1. 应用程序池要选v4.xx&#xff0c;托管模式选“集成” 2. 把asp.net 4.xx安装在iis上&#xff0c;方法&#xff1a; cd \Windows\Microsoft .NE…

基于Flask的东方财富网股票数据可视化分析系统

【大数据】基于Flask的东方财富网股票数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统能够高效地从东方财富网抓取股票数据&#xff0c;并通过Python的强大数据处理能…

整形在内存中的存储(例题逐个解析)

目录 一.相关知识点 1.截断&#xff1a; 2.整形提升&#xff1a; 3.如何 截断&#xff0c;整型提升&#xff1f; &#xff08;1&#xff09;负数 &#xff08;2&#xff09;正数 &#xff08;3&#xff09;无符号整型&#xff0c;高位补0 注意&#xff1a;提升后得到的…

HarmonyOS第26天:应用发布与推广全攻略:从0到1走向市场

一、引言:开启 HarmonyOS 应用之旅 在数字化时代的浪潮中,HarmonyOS 以其独特的分布式理念和强大的跨设备协同能力,为应用开发领域开辟了一片崭新的天地。随着 HarmonyOS 市场份额的稳步增长,其生态设备数量已突破 9 亿大关,吸引了超过 254 万开发者投身其中 ,成为了开发…

【操作系统安全】任务4:Windows 系统网络安全实践里常用 DOS 命令

目录 一、引言 二、网络信息收集类命令 2.1 ipconfig 命令 2.1.1 功能概述 2.1.2 实例与代码 2.2 ping 命令 2.2.1 功能概述 2.2.2 实例与代码 2.3 tracert 命令 2.3.1 功能概述 2.3.2 实例与代码 三、网络连接与端口管理类命令 3.1 netstat 命令 3.1.1 功能概述…

《我的Python觉醒之路》之转型Python(十五)——控制流

[今天是2025年3月17日&#xff0c;继续复习第一章节、第二章节的内容 ] 《我的Python觉醒之路》之转型Python&#xff08;十四&#xff09;——控制流

通过 SVG 使用 AI 生成理想图片:技术实现与实践指南

文章目录 1. SVG 与 AI 的结合&#xff1a;技术价值2. 技术原理&#xff1a;AI 如何生成 SVG&#xff1f;3. 实现步骤&#xff1a;从需求到图形3.1 定义需求3.2 使用 AI 生成 SVG3.3 验证与调整 4. 代码解析&#xff1a;实现科技感的关键4.1 渐变背景4.2 网格线条4.3 发光六边形…

OpenCV计算摄影学(22)将输入的彩色图像转换为两种风格的铅笔素描效果函数pencilSketch()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 铅笔风格非写实线描图。 该函数通过图像处理技术将输入的彩色图像转换为两种风格的铅笔素描效果&#xff1a; dst1&#xff1a;炭笔效果的灰度图…

JavaScript运算符与流程控制详解

一、运算符 • 赋值运算符 • 一元运算符 • 比较运算符 • 逻辑运算符 • 运算符优先级 1.算术运算符 数字是用来计算的&#xff0c;比如&#xff1a;乘法 * 、除法 / 、加法 、减法 - 等等&#xff0c;所以经常和算术运算符一起。 算术运算符&#xff1a;也叫数学运算符&…

设计模式(行为型)-观察者模式

目录 定义 类图 角色 Subject&#xff1a;抽象主题&#xff08;抽象被观察者&#xff09;​ ConcreteSubject&#xff1a;具体主题&#xff08;具体被观察者&#xff09;​ Observer&#xff1a;抽象观察者​ ConcrereObserver&#xff1a;具体观察者​ 优缺点 优点​…

调用华为云API实现口罩识别

1.作者介绍 范小雨&#xff0c;女&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;1019044907qq.com 高金年&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生&#…

C++中的单例模式及具体应用示例

AI 摘要 本文深入探讨了C中的单例模式及其在机器人自主导航中的应用&#xff0c;特别是如何通过单例模式来管理地图数据。文章详细介绍了单例模式的基本结构、优缺点以及在多线程环境中的应用&#xff0c;强调了其在保证数据一致性和资源管理中的重要性。 接着&#xff0c;文章…

【STM32】从新建一个工程开始:STM32 新建工程的详细步骤

STM32 开发通常使用 Keil MDK、STM32CubeMX、IAR 等工具来创建和管理工程。此处是 使用 Keil MDK5 STM32CubeMX 创建 STM32 工程的详细步骤。 新建的标准库工程文件已上传至资源中&#xff0c;下载后即可直接使用。 标准库新建 STM32 工程的基本目录结构&#xff1a;STD_STM…

Java 大视界 -- 基于 Java 的大数据实时流处理中的窗口操作与时间语义详解(135)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

Fastdata极数:中国民宿行业发展趋势报告2025

2024年&#xff0c;中国游客出行次数大幅上涨&#xff0c;旅游相关支出也复苏强劲。2025年中国旅游业还将持续稳健的复苏及增长。同时&#xff0c;中国旅游业将见证一场深刻的变革&#xff0c;这场变革的推动力是消费者对旅游期望的转变&#xff0c;经济因素和年轻人全新价值观…

【自定义微信小程序拉下选择过滤组件】searchable-select

【自定义微信小程序拉下选择过滤组件】searchable-select 组件说明 点击输入框获取焦点&#xff0c;输入内容&#xff0c;自动匹配搜索结果&#xff0c;点击搜索结果&#xff0c;自动填充搜索结果。 组件使用 将组件文件夹放在项目中。在需要使用的页面的json文件中&#x…

推理大模型的后训练增强技术-Reasoning模型也进化到2.0了,这次居然学会用工具了

论文题目&#xff1a;START: Self-taught Reasoner with Tools 论文链接&#xff1a;https://arxiv.org/pdf/2503.04625 论文简介 Reasoning模型也进化到2.0了&#xff0c;这次居然学会用工具了&#xff01;✨ 最近有个叫START的方法&#xff0c;让大模型也能学着用工具&#…

Idea集成docker通过ca加密实现镜像打包

​ Idea集成docker实现镜像打包_ideadocker镜像打包-CSDN博客 ​ 之前通过这种方式虽然可以实现idea通过maven打jar包的同时把docker镜像也进行打包&#xff0c;但是这种方式存在很大漏洞&#xff0c;就是服务器的2375端口大开&#xff0c;任何人拿着idea通过这种方式都可以连…

SOC与电压的关系

与电池相关的参数都与SOC有关&#xff0c;也就是电池剩余容量的百分比即荷电状态。 SOC百分之二十时&#xff0c;对应3.2V,SOC80&#xff05;时对应3.3V。

塔能科技:做节能界的“催化剂”,加速工厂能源改造变革

在全球坚定不移地迈向可持续发展的宏大进程中&#xff0c;节能降耗早已从一种发展理念&#xff0c;深度融入到经济社会发展的每一个脉络之中&#xff0c;成为企业在激烈市场竞争中实现降本增效的核心策略&#xff0c;更是推动整个社会朝着绿色、低碳、循环方向转型的关键支撑点…