《C++ Primer》第3章 字符串、向量和数组(三)

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

3.5 数组(P101)

数组类似于 vector ,不同点在于数组的大小固定不变,在某些情况下性能较好,但灵活性较差。

3.5.1 定义和初始化内置数组(P101)

数组是一种复合类型,声明形如 a[d] ,其中 d 是数组的维度。维度必须大于 0 且必须是一个常量表达式。默认情况下,数组的元素被默认初始化

如果在函数内部定义了内置类型的数组,则默认初始化会令数组含有未定义的值。

定义数组时必须指定数组类型,不允许通过 auto 推断元素类型。不存在引用的数组。

显式初始化数组元素

可以对数组进行列表初始化,此时可以忽略数组的维度:

  • 如果声明数组时没有指明维度,编译器会根据初始值的数量计算出维度。
  • 如果指明了维度,那么初始值的数量不能超过维度,如果初始值的数量小于维度,则剩下的元素被初始化为默认值

内置类型的默认值为 0 ,类类型执行类的默认初始化。

字符数组的特殊性

可以使用字符串字面值对字符数组进行初始化,此时需要留意字符串字面值结尾的空字符 '\0'

不允许拷贝和赋值

不能将数组的内容拷贝给其他数组作初始值;不能用数组为其他数组赋值:

int a[] = {0 ,1, 2};
int a1[] = a;    // 错误
a1 = a;    // 错误

理解复杂的数组声明

默认情况下,修饰符由内向外由右向左依次绑定:

int *ptrs[10];    // 含有10个int*的数组// 指向含有10个int元素的数组的指针
int (*Parray)[10] = &arr;
// 这里遇到一个问题,&arr会被编译器识别成int (*)[10]类型,而arr会被编译器识别成int *类型

3.5.2 访问数组元素(P103)

数组的元素可以用范围 for 语句或下标运算符进行访问。使用数组下标时,通常将其定义为 size_t 类型。size_t 是与机器相关的无符号类型,定义在 cstddef 头文件中。

后面会提到,下标运算符可以接受负数,所以这里是“通常”使用 size_t

数组使用的下标运算符是由 C++ 语言直接定义的,可以用于任何数组类型。

检查下标的值

下标大于 0 而小于数组大小。

3.5.3 指针和数组(P105)

在很多用到数组名字的地方,编译器会自动将其替换为一个指向数组首元素的指针

string nums[] = {"one", "two", "three"};
string *p = nums;    // 等价于p = &nums[0]

使用 decltype 关键字时,上述转换不会发生;使用 sizeof 运算符时,数组名代表整个数组;使用 &数组名 时,得到的是指向整个数组的指针

指针也是迭代器

vector 迭代器支持的运算,指向数组元素的指针全部支持。

标准库函数beginend

C++11 新标准引入了 beginend 函数,参数均为数组:

int ia[] = {0, 1, 2, 3, 4};
int *b = begin(ia), *e = end(id);

指针运算

两个指针相减的类型为 ptrdiff_t ,是定义在 cstddef 中的机器相关的有符号类型

指针的比较同样适用于空指针和所指对象非数组的指针。

解引用和指针运算的交互

int ia[] = {0, 1, 2, 3, 4};
int last = *(ia+4);

下标和指针

对数组执行下标运算实质上是对指向数组元素的指针执行下标运算:

int i = ia[2];int *p = ia;
i = *(p+2);

内置的下标运算可以处理负值;标准库类型的下标运算使用的下标必须为无符号数( ::size_type ),不能处理负值。

3.5.4 C风格字符串(P109)

尽量不要使用 C 风格字符串,因为其容易引发安全漏洞。

字符串字面值是 C 风格字符串的实例。C 风格字符串是一种约定俗成的写法,把字符串存放在字符数组中,并以空字符结尾。

C标准库string函数

image-20230914144656327

上述函数定义在 cstring 头文件中,函数的参数均为指向以空字符结尾的字符数组的指针,但函数本身并不负责验证这一点。所以如果传入一个不以空字符结尾的字符数组的指针,可能会发生错误。

比较字符串

目标字符串的大小由调用者决定

在执行 C 风格字符串的拼接和复制操作时,必须保证目标字符串有足够的空间。

3.5.4 与旧代码的接口(P111)

混用string对象和C风格字符串

任何出现字符串字面值的地方,都可以用以空字符结尾的字符数组来替代:

  • 允许使用以空字符结尾的字符数组为 string 对象初始化或赋值。
  • string 的加法运算中允许其中一个运算对象为以空字符结尾的字符数组。

如果想用 string 对象初始化一个字符数组,可以使用 string 类中的 c_str 函数:

string s("hello");
const char *str(s);    // 错误
const char *str(s.c_str());    // 正确,但不推荐

c_str 函数的返回值类型是 const char* ,指向一个以空字符结尾的字符数组,该数组所存的内容恰好与 string 对象中的内容一致。需要注意的是,c_str 返回的数组可能会因为其 string 对象的改动而失效,所以最好在执行 c_str 后对字符数组进行拷贝:

char *str = new char[20];
strcpy(str, s.c_str);

使用数组初始化 vector 对象

允许用数组初始化 vector 对象,需要给出数组的首元素地址和尾后地址:

int ia[] = {0, 1, 2, 3, 4};
vector<int> iv(begin(ia), end(ia));
vector<int> iv1(ia, ia+1);    // 使用数组中的部分元素初始化vector

现代 C++ 程序应尽量使用 vectorstring 和迭代器,而避免使用数组、C 风格字符串和指针。

3.6 多维数组(P112)

严格来说,C++ 没有多维数组,只有数组的数组:

int ia[3][4];    // ia为维度为3的数组,其中的元素是维度为4的int数组

多维数组的初始化

下面的两种写法是等价的:

int ia[2][2] = {{0, 1},{2, 3}
};
int ia[2][2] = {0, 1, 2, 3};

在列表初始化多维数组时,不必列出所有元素,未列出的元素执行默认值初始化。下面两种写法的含义不同:

int ia[2][2] = {{0}, {1}
};
int ia[2][2] = {0, 1}

多维数组下标的引用

使用范围for语句处理多维数组

int ia[3][4] = {};
for(const auto &row : ia){for(auto column : row){cout << col << endl;}
}

注意,外层循环的控制变量必须声明成引用类型,否则控制变量将被设置为指针类型

指针和多维数组

多维数组实际上数组的数组,所以数组名转换得来的指针指向第一个内层数组:

int ia[3][4] = {};
int (*p)[4] = ia;

使用 autodecltype 可以避免复杂的数组指针:

for(auto p=begin(ia);p!=end(ia);p++){for(auto q=begin(*p);q!=end(*p);q++){cout << *q << endl;}
}

类型别名简化多维数组指针

using int_array int[4];
int_array *p = ia;

cltype` 可以避免复杂的数组指针:

for(auto p=begin(ia);p!=end(ia);p++){for(auto q=begin(*p);q!=end(*p);q++){cout << *q << endl;}
}

类型别名简化多维数组指针

using int_array int[4];
int_array *p = ia;

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

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

相关文章

SpringBoot项目中使用poi-tl打成jar包后常见问题及解决

目录 前言 一、场景描述 1、打成jar包运行后模板找不到 2、文件只能下载一次 二、正确示范 1、Controller下载方法定义 2、文档生成 总结 前言 在前面的博客中&#xff0c;介绍了如何在Java中根据模板动态写入数据到word模板中&#xff0c;原文地址&#xff1a;Java使用…

Pandas数据分析一览-短期内快速学会数据分析指南(文末送书)

前言 三年耕耘大厂数据分析师&#xff0c;有些工具是必须要掌握的&#xff0c;尤其是Python中的数据分析三剑客&#xff1a;Pandas&#xff0c;Numpy和Matplotlib。就以个人经验而已&#xff0c;Pandas是必须要掌握的&#xff0c;它提供了易于使用的数据结构和数据操作工具&am…

第69步 时间序列建模实战:ARIMA建模(R)

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们使用R进行SARIMA模型的构建。 同样&#xff0c;这里使用这个数据&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Re…

uniapp小程序 - 隐私协议保护指引接入教程

文章目录 前提&#xff1a;__usePrivacyCheck__: true步骤一、封装弹窗组件步骤二、单个页面引用一、被动监听二、主动查询 前言&#xff1a;官方发布公告&#xff0c;自2023年9月15日起&#xff0c;对于涉及处理用户个人信息的小程序开发者&#xff0c;仅当开发者主动向平台同…

idea VCS配置多个远程仓库

Idea VCS配置多个远程仓库 首先要有两个或多个不同远程仓库地址 idea 添加数据源 查看推送记录 添加数据源 ok之后填写账号密码 推送本地项目 选择不同远程地址 push 查看不同远程地址的 不同分支的 推送记录 不期而遇的温柔&#xff1a; 应用开源架构进行项目开发&#xff0…

【新版】系统架构设计师 - 软件架构设计<新版>

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 软件架构设计&#xff1c;新版&#xff1e;考点摘要概念架构的 4 1 视图架构描述语言ADL基于架构的软件开发方法ABSDABSD的开发模型ABSDMABSD&#xff08;ABSDM模型&#xff09;的开发过程 软件架…

k8s node环境部署(三)

1、添加node1、node2环境 前面配置master环境的截图最后一段 复制下来 分别在node主机执行 kubeadm join 192.168.37.132:6443 --token p5omh3.cqjqt8ymrwkdn2fc \ --discovery-token-ca-cert-hash sha256:608a1cbadd060cfdeac2fae84c19609061b750ab51bf9a19887ff7ea…

C# 辗转相除法求最大公约数

辗转相除法求最大公约数 public static void CalcGCD(int largeNumber, int smallNumber, out int GCD){GCD 1;int remain -1;while (remain ! 0){remain largeNumber % smallNumber;GCD smallNumber;largeNumber smallNumber;smallNumber remain;}}

从零基础到精通Flutter开发:一步步打造跨平台应用

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 导言 Flutter是一种流行…

Java开发之框架(spring、springmvc、springboot、mybatis)【面试篇 完结版】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、框架知识分布二、Spring1. spring-单例bean① 问题引入② 单例bean是线程安全的吗③ 问题总结④ 实战面试 2. spring-AOP① 问题引入② AOP记录操作日志③ …

基于SSM+Vue的中国咖啡文化宣传网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用vUE技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【JAVA-Day09】 Java注释详解:一般注释、文档注释与最佳实践

Java注释详解&#xff1a;一般注释、文档注释与最佳实践 Java注释详解&#xff1a;一般注释、文档注释与最佳实践摘要引言一、一般注释1.1 块注释1.2 单行注释1.3 尾端注释 二、文档注释三、注释的最佳实践四、总结参考资料 博主 默语带您 Go to New World. ✍ 个人主页—— 默…

TheRouter 框架原理

TheRouter 框架入口方法 通过InnerTheRouterContentProvider 注册在AndroidManifest.xml中&#xff0c;在应用启动时初始化 <application><providerandroid:name"com.therouter.InnerTheRouterContentProvider"android:authorities"${applicationId}.…

【AI】机器学习——线性模型(线性回归)

线性模型既能体现出重要的基本思想&#xff0c;又能构造出功能更加强大的非线性模型 参考&#xff1a;唐宇迪机器学习课程 文章目录 3.1 线性模型3.1.1 数据3.1.2 目标/应用 3.2 线性回归3.2.1 回归模型历史3.2.2 回归分析研究内容回归分析步骤 3.2.3 回归分析分类3.2.4 回归模…

Flutter的oktoast插件详解

文章目录 简介详细介绍安装和导入导入在MaterialApp外面套一层OKToast组件为什么是包住MaterialApp&#xff1f; 显示Toast消息&#xff1a; 高级使用Toast位置Toast持续时间自定义Toast样式高级用法 使用场景提示消息表单验证操作反馈网络请求状态调试信息小结 总结 简介 okt…

数据治理中的核心元素——元数据

一、什么是元数据&#xff1f; 元数据是关于数据的组织&#xff0c;数据域及其关系的信息&#xff0c;简单来说&#xff0c;元数据就是被用来描述数据的信息。元数据是一个涵盖大量信息的数据集合。元数据可以为数据说明其元素或者属性&#xff08;名称&#xff0c;大小&#x…

029:vue项目,勾选后今天不再弹窗提示

第029个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

多元函数的微分法

目录 复合函数微分法 隐函数微分法 复合函数求导与全微分 隐函数偏导数与全微分 复合函数微分法 复合函数微分法是一种求导方法&#xff0c;用于计算复合函数的导数。 假设有一个复合函数yf(u)&#xff0c;其中ug(x)&#xff0c;则复合函数微分法可以用于计算y对x的导数。根…

使用SpringCloud Eureka 搭建EurekaServer 集群- 实现负载均衡故障容错【上】

&#x1f600;前言 本篇博文是关于使用SpringCloud Eureka 搭建EurekaServer 集群- 实现负载均衡&故障容错&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可…

Kafka3.0.0版本——消费者(独立消费者消费某一个主题数据案例__订阅主题)

目录 一、独立消费者消费某一个主题数据案例1.1、案例需求1.2、案例代码1.3、测试 一、独立消费者消费某一个主题数据案例 1.1、案例需求 创建一个独立消费者&#xff0c;消费firstTopic主题中数据&#xff0c;所下图所示&#xff1a; 注意&#xff1a;在消费者 API 代码中必…