《C++ Primer Plus》《4、复合类型》

文章目录

  • 前言:
  • 1 数组
    • 1.1数组的初始化规则
    • 1.2 C++11的数组初始化方法
  • 2 字符串
    • 2.1 拼接字符串常量
    • 2.2在数组中使用字符串
    • 2.3 字符串输入
    • 2.4 每次读取一行字符串输入
    • 2.5 混合输入字符串和数字
  • 3 string类简介
    • 3.1 C++11字符串初始化
    • 3.2 赋值、拼接、附加
    • 3.3 string类的其他操作
    • 3.4 string类I/O
  • 4 结构简介
    • 4.1 在程序中使用结构
    • 4.2 C++11结构初始化
    • 4.3 结构可以将string类的关系
    • 4.4 其他结构属性
    • 4.5 结构数组
    • 4.6结构中的位字段
  • 5 共用体
  • 6 枚举
    • 6.1 设置枚举值的值
    • 6.2 枚举的取值范围
  • 7指针和自由存储空间
    • 7.1声明和初始化指针
    • 7.2指针的危险
    • 7.3指针和数字
    • 7.4使用new来分配内存
    • 7.5使用delete释放内存
    • 7.6使用new来创建动态数组
  • 8指针、数组和指针算数
    • 8.1程序说明
    • 8.2指针小结
    • 8.3指针和字符串
    • 8.4使用new创建动态结构
    • 8.5自动存储、静态存储和动态存储
  • 9 类型组合
  • 10 数组的替代品
    • 10.1模板类vector
    • 10.2模板类array(C++11)
    • 10.3 比较数组,vector对象,array对象
  • 11 总结
  • 12 参考

前言:

第三章介绍了基本的数据类型:整型与浮点型,相对来说比较基础,但是不足以应付实际的复杂情况,为了更加灵活地使用数据,语言开发者推出了复合类型。

1 数组

当你要记录班级中同学的身高时,之前的方法,班级有多少人,你就要创建多少个int类型的变量,然后一个一个地记录下来。这很繁琐,效率也很低;生活中类似的场景很多,这时候需要一个结构来存储同种类型的变量,应这种实际开发需求,诞生了数组这种变量类型。
数组是一种数据格式,能够存储多个同类型的数值。要创建数组需要使用声明语句。需要声明三点:

  • 1)存储在每个元素中的类型;
  • 2)数组名称;
  • 3)数组中的元素个数;

例子:

short Months[12]

在这里插入图片描述

数组的名称为Months,数组一共有12个元素,每个元素存储的类型是short类型。
注意:在编写程序的过程中,不会检查数组的下标是否有效,编译时不会出错但在实际运行过程中可能会引发问题。

1.1数组的初始化规则

  • 1)只有在定义数组时才能进行初始化,不能先声明然后整体再进行初始化;
  • 2)如果只对一部分元素进行初始化,剩余的元素都被设置为0;
  • 3)初始化数组不声明元素个数,C++编译器将计算元素个数;

1.2 C++11的数组初始化方法

  • 1)初始化数组时可以省略“等号”运算符;
  • 2)可以不在大括号内包含任意东西,默认所有元素都是0;
  • 3)列表初始化禁止缩窄“转换”。

2 字符串

代码是为了处理现实世界中的工作,不可能只有数字而没有字符,还是举之前的例子,在对班级同学的成绩做记录时,只记录成绩毫无意义,要把这个成绩背后的名字也记录下来,这样之前的数字才有意义,所以字符串是非常重要的数据类型,它可以帮助我们处理和操作各种文本数据,并且可以通过标准库中提供的函数轻松地完成各种文本操作。
字符串是存储在内存的连续字节的一系列字符。即字符串是存储在char数组中的,空字符被写作“\0”,同时字符串也是以\0进行结尾的。

2.1 拼接字符串常量

有时候,单个字符串过于冗长,C++允许拼接字符串的字面值,即将两个用引号括起来的字符串合并为一个。

2.2在数组中使用字符串

要将字符串存储到数组中,常用的有两种方法:
1)将数组初始化为字符串常量;
2)将键盘或文件输入读入到数组中;
书中给出了示例程序,用了“sizeof”与”strlen”,区别是:”sizeof”计算整个数组的长度,而“strlen”只是计算可见的字符,并不把空字符算在内。
在这里插入图片描述

2.3 字符串输入

在示例的程序中,输入了两个单词,后续便直接将这两个单词赋值给两个变量,然后立马显示最后一行。通过cin完成字符的输入,cin使用空白(空格,制表符,换行符)来确定字符串的结束位置,这意味着cin在获取字符串数组输入时只读取一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。

2.4 每次读取一行字符串输入

有时候不一定按单词个数进行读取,也可以按行进行读取。istream中的类提供了一些面向行的类成员函数:getline()和get()。

  • 1)面向行的输入:getline()

    getline()读取整行,它使用通过回车键输入的换行符来确定输入结尾。
    cin.getline()有2个参数,第一个参数用来存储输入行的数组的名称,第二个参数是要读取的字符数。getline()函数每次读取一行,他通过换行符来确定行尾,但不保存换行符,在存储字符串时,他将空字符来代替换行符。
    在这里插入图片描述

  • 2)面向行的输入:get()

    连续调用2次cin.get()示例:
    cin.get(name,ArSize)
    cin.get(dessert,ArSize)
    由于第一次调用,换行符留在输入队列中,因此第二次调用时看到的第一个字符便是换行符。cin.get()会认为已经到达行尾,而没有发现任何可读取的内容。
    解决办法是:用cin.get()来处理换行符。
    3)空行和其他问题
    当使用getline()或者get()读取空行时,下一条输入语句将在前一句getline()或者get()结束读取的位置开始读取。但这意味着接下来的输入将被阻断,可以用cin.clear()进行恢复。

2.5 混合输入字符串和数字

书中给出了示例代码,在混合输入的情况下,有些输入无法实现。在第一次读取过程中,按回车键生成的换行符留在了输入队列中,后面的cin.getline()看到换行符之后以为是一个空行,所以后续的输入便无法实现。解决方法是:在读取地址之前先读取并舍弃换行符,这样便能解决这个问题。

3 string类简介

通过添加string类扩展了C++库,以后便可以使用string类的对象来存储字符串。书中给出了示例来介绍string类的用法。从中我们可以得知:
1)可以使用C风格初始化string对象;
2)可以使用cin将键盘输入存储到string对象中;
3)可以使用cout来显示string对象;
4)可以使用数组表示法来访问存储在string对象中的字符。

3.1 C++11字符串初始化

可以用字符数组,string类方法进行初始化2种方法:
char a[] = {“aaaaa”};
string b = {“bbbbbb”};

3.2 赋值、拼接、附加

赋值:可以将一个string对象赋值给另一个string对象;
拼接:直接用+运算符,将两个字符串相加。

3.3 string类的其他操作

C语言风格字符串对字符串进行操作的时候,提供了一些函数,strcpy用于函数的复制,strcat用于函数的拼接;strlen()函数用于获得字符串的长度。

3.4 string类I/O

当输入为一个简单的单词的时候,是用简单的cin,cout运算符,当要读取一行输入内容而不是一个单词的时候,可以用getline()来获取。

4 结构简介

结构是一种比数组更灵活的数据格式,因为同一个结构可以存储多种类型的数据,从而将数据的表示合并到一起。结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。所以创建结构包括两步:
(1)定义结构描述,描述并标记了能够存储在结构中的各种数据类型;
(2)按描述创建结构变量。

结构描述的组成部分
在这里插入图片描述

4.1 在程序中使用结构

书中给出了示例代码,声明了一个结构体,并调用了结构体对象。C++中建议将结构体声明在外部,这样各个函数都能使用。
在这里插入图片描述

4.2 C++11结构初始化

C++11支持结构体进行列表初始化;如果大括号里不包含任何东西,各个成员都被设置为0.

4.3 结构可以将string类的关系

可以,将之前的char数组转化为string,更加好用。

4.4 其他结构属性

可以使用赋值运算符,将结构赋值给另一个同类型的结构体,这种赋值称为成员赋值。介绍了一些初始化的特殊方法,不建议使用,结构体的声明,初始化,使用按部就班的来。

4.5 结构数组

顾名思义就是元素全都是结构体的数组,方法和创建基本类型的数组完全一致;书中给出了代码示例。

4.6结构中的位字段

允许指定占用特定位数的结构成员,使得结构体与硬件上的寄存器相对应。

5 共用体

共用体是一种数据格式,它能存储不同的数据类型,但只能同时存储其中的一种类型。使用共同体,当数据项使用两种或者更多格式的时候,可以节省空间。

6 枚举

enum工具提供了一种创建符号常量的方式,允许定义新类型,但必须按照严格的限制进行。

6.1 设置枚举值的值

可以使用赋值运算符来显示地设置枚举量的数值。指定的数值必须是整数,也可以只显示地定义其中一些枚举量的数值。
补充:可以创建多个数值相同的枚举量。

6.2 枚举的取值范围

C++11扩展了枚举,增加了作用域内枚举;C++的枚举范围更加灵活,下限一般情况是0,上限由最大的枚举数值决定,由大于这个数值的,最小2次幂确定。例如枚举中一个数值为108,大于108的最小2次幂是128,此时最大枚举数值便是127,枚举范围为[0,127]。

7指针和自由存储空间

计算机存储数据需要明确的3种基本属性:
(1)信息存储在何处
(2)存储的值为多少
(3)存储的信息是什么类型
指针是C++语言的精髓,只有灵活地使用指针,才能真正掌握C++语言。

7.1声明和初始化指针

书中给出了示例程序,声明和初始化了指针。
在这里插入图片描述

7.2指针的危险

在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配存储指针所指向数据的内存。

7.3指针和数字

指针的表示形式是数字,表示的意义是位置。

7.4使用new来分配内存

为一个数据对象获得并指定分配内存的通用格式:
typename * pointer_name = new typeName

7.5使用delete释放内存

一定要配对地使用new和delete,否则会发生内存泄漏。

7.6使用new来创建动态数组

  • 1、使用new来创建动态数组
  • 2、使用动态数组

8指针、数组和指针算数

指针和数组基本等价的原因在于指针算术和C++内部处理数组的方式。书中给出了示例程序验证了这一点。

8.1程序说明

C++将数组名解释为第一个元素的地址。
在这里插入图片描述

8.2指针小结

1、声明指针
2、给指针赋值
3、对指针解除引用
4、区分指针和指针所指向的数值
5、数组名
6、指针算术
7、数组的动态联编和静态联编
8、数组表示法和指针表示法

8.3指针和字符串

主要介绍了strcpy函数,strcpy函数暗暗包含了new的操作,虽然是复制,内容会进行复制,但是变量地址的值是全新的。

8.4使用new创建动态结构

书中给出了示例程序。

8.5自动存储、静态存储和动态存储

分别对应自动变量,静态变量;new和delete运算符,共同管理一个内存池,使得数据的生命周期不完全受程序或函数的生存时间控制。

9 类型组合

第四章介绍了数组,结构以及指针,书中给了一个示例,来对他们进行访问。来看其中四个cout。

1、trio->year

trio是结构体数组的首地址,打印出来的是trio[0].year;

2、arp[1]->year

打印的是s02.year

3(*ppa)->year

声明的ppa是一个指向指针地址的指针,打印的是s01.year;

4、(*(ppb+1))->year

打印的是s02.year.

10 数组的替代品

模板类vector与array是数组的替代品。

10.1模板类vector

在C++中,vector是一个标准库容器,用于存储和管理动态大小的元素序列。它提供了许多内置的函数和操作符,使得元素的插入、删除和访问变得非常方便。
vector的主要作用包括:

  • 动态大小:vector可以根据需要动态调整大小,可以在任意位置插入或删除元素,而不需要手动管理内存。这使得它比数组更具灵活性。
  • 高效的随机访问:vector中的元素在内存中是连续存储的,因此可以通过索引快速访问任何元素。这使得vector非常适合需要频繁随机访问的场景。
  • 尾部插入和删除:vector提供了push_back()和pop_back()等函数,可以高效地在尾部插入和删除元素。这对于实现栈(stack)和队列(queue)等数据结构很有用。
  • 可以使用迭代器遍历:vector支持使用迭代器进行元素的遍历。迭代器提供了一种统一的方式来访问和处理容器中的元素。
  • 自动内存管理:vector负责管理内部存储空间的分配和释放,使得开发者无需手动处理内存分配和释放的细节。
    总之,vector是一个强大而灵活的容器,适用于各种情况下需要动态管理元素序列的场景。无论是存储对象、构建数据结构还是进行算法实现,vector都是C++中常用的工具之一。
    模板类vector类似于string类,是一种动态数组,
    (1)使用前提:包含vector头文件,使用using编译指令;
    (2)如何使用:
    创建一个名为vt的vector对象,可以存储n_elem个类型为typeName的元素;
vector<typeName> vt(n_elem);

其中n_elem可以是整型常量,也可以是整型变量。

10.2模板类array(C++11)

在C++中,array是一个用于存储固定大小的相同类型元素序列的容器类模板。它起到以下作用:

  • 存储数据:array可以存储一组具有相同数据类型的元素。它提供了连续的内存空间来存储这些元素。
  • 快速访问:由于array中的元素是连续存储的,可以通过索引快速访问特定位置的元素。数组的索引从0开始,因此可以使用索引来直接访问数组中的元素。
  • 高效的元素访问和修改:与其他容器(如vector或list)相比,array提供了更高效的元素访问和修改。由于元素是连续存储的,可以利用指针算术来进行高效的访问和修改操作。
  • 固定大小:array在创建时需要指定固定的大小,并且无法动态调整。这意味着一旦创建了一个array,它的大小就不能改变。这种固定大小的特性可确保在编译时就分配了足够的内存空间。
  • 与原生数组的兼容性:array提供了与原生数组相似的语义和行为。它可以被传递给期望原生数组参数的函数,并且可以与使用原生数组的代码进行交互。

总而言之,array在C++中提供了一种方便的方式来存储和访问固定大小的连续元素序列,并且具有高效的性能。
array对象的长度是固定的,使用栈(静态内存分配),其效率与数组相同,但更方便,安全。在声明中创建一个名为arr的array对象,它包含n_elem个类型为typeName的元素:

array<typeName,n_elem> arr;

10.3 比较数组,vector对象,array对象

书中给出了示例,对数组,array,vector三者的对象输出他们的数值以及地址,但是对数组下标使用了-2这个索引,编译不会警告,数组名称本质上是一个地址,-2的索引,表示输出这个指针之前指向的数据。但是在执行过程中叫做“越界”,就会出现问题。
为了在vector与array中避免这种情况发生,使用at(),在函数运行期间捕获非法索引,若是下标不符合规范,程序运行过程中默认会中断。

11 总结

很多类型在学习C语言的时候都或多或少接触过,数组,字符串,指针的使用频率很高,多看几遍也无妨。数组的替代品,array以及vector比较重要,这都是C++新增的,需要重点关注一下。

12 参考

12.1 《C++ Primer Plus》

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

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

相关文章

CPU是如何工作的?什么是冯·诺依曼架构和哈弗架构?

《嵌入式工程师自我修养/C语言》系列——CPU是如何工作的&#xff1f;什么是冯诺依曼架构和哈弗架构&#xff1f; 一、CPU内部结构及工作原理1.1 CPU的结构1.2 CPU工作流程举例 二、计算机体系结构2.1 冯诺依曼架构2.2 哈弗架构 三、总结 快速学习嵌入式开发其他基础知识&#…

SpringBoot3 + Vue3 由浅入深的交互 基础交互教学

说明&#xff1a;这篇文章是适用于已经学过SpringBoot3和Vue3理论知识&#xff0c;但不会具体如何实操的过程的朋友&#xff0c;那么我将手把手从教大家从后端与前端交互的过程教学。 目录 一、创建一个SpringBoot3项目的和Vue3项目并进行配置 1.1后端配置: 1.1.1applicatio…

notepad++打开文本文件乱码的解决办法

目录 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#xff0c;红框圈出来的一个个试。我切换到UTF-8编码就正常了。 乱码如图。下面分享我的解决办法 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#…

基于ORB-SLAM2与YOLOv8剔除动态特征点

基于ORB-SLAM2与YOLOv8剔除动态特征点 以下方法以https://cvg.cit.tum.de/data/datasets/rgbd-dataset/download#freiburg3_walking_xyz数据集进行实验测试APE 首先在不剔除动态特征点的情况下进行测试&#xff1a; 方法1:segment坐标点集合逐一排查剔除 利用YOLOv8的segm…

自定义Linux登录自动提示语

设置提示语的方式 在Linux系统中&#xff0c;可以通过修改几个特定的文件来实现在用户登录时自动弹出提示语。以下是几个常用的方法&#xff1a; 1. 修改/etc/issue文件&#xff1a; 这个文件用于显示本地登录前的提示信息 sudo vi /etc/issue在项目合作的时候&#xff0c;…

VMware虚拟机安装CentOS7

对于系统开发来说&#xff0c;开发者时常会需要涉及到不同的操作系统&#xff0c;比如Windows系统、Mac系统、Linux系统、Chrome OS系统、UNIX操作系统等。由于在同一台计算机上安装多个系统会占据我们大量的存储空间&#xff0c;所以虚拟机概念应运而生。本篇将介绍如何下载安…

鉴源论坛 · 观模丨形式化工程方法之需求建模(上)

作者 | 杨坤 上海控安可信软件创新研究院系统建模组 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 引言&#xff1a;需求建模是整个软件开发、测试验证与维护的基础。经过长期研究与实践&#xff0c;工业界与学术界均意识到&…

Linux之Shell

第 1 章 Shell 概述 1&#xff09;Linux 提供的 Shell 解析器有 [zhaohadoop101 ~]$ cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/tcsh /bin/csh2&#xff09;bash 和 sh 的关系 [zhaohadoop101 bin]$ ll | grep bash -rwxr-xr-x. 1 root root 941880…

JVM--- 垃圾收集器详细整理

目录 一、垃圾收集需要考虑的三个事情&#xff1a; 二、垃圾回收针对的区域 三、如何判断对象已死 1.引用计数算法&#xff1a; 2.可达性分析算法 四、引用 五、生存还是死亡&#xff1f; 六、回收方法区 七、垃圾收集算法 1.分代收集理论 2.标记-清除算法 3.标记-复制算…

【qt创建线程两种方式】

QT使用线程的两种方式 1.案例进度条 案例解析&#xff1a; 如图由组件一个进度条和三个按钮组成&#xff0c;当点击开始的时候进度条由0%到100%&#xff0c;点击暂停&#xff0c;进度条保持之前进度&#xff0c;再次点击暂停变为继续&#xff0c;点击停止按钮进度条停止。 案…

案例:CentOS8 在 MySQL8.0 实现半同步复制

异步复制 MySQL 默认的复制即是异步的&#xff0c;主库在执行完客户端提交的事务后会立即将结果返给给客户端&#xff0c;并不关心从库是否已经接收并处理&#xff0c;这样就会有一个问题&#xff0c;主节点如果 crash 掉了&#xff0c;此时主节点上已经提交的事务可能并没有传…

.NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库

一、效果 记录日志为文档 记录日志到数据库 二、添加NuGet包 三、log4net.config代码配置 <?xml version"1.0" encoding"utf-8" ?> <log4net><!-- Debug日志 --><appender name"RollingFileDebug" type"log4net…

Java学习24--异常

异常 软件运行过程中的各种意料之外叫做Exception&#xff0c;比如要读取的文件找不到&#xff0c;准备联网发现没网&#xff0c;等着int参数来了个String 注意Error和exception不一样&#xff0c;error错的比较猛&#xff0c;一般是直接把JAVA整个搞崩了&#xff0c;比如内存…

数据结构通讲

目录 集合源码详解 一、常见数据结构讲解 1. 线性数据结构 1.1 数组 1.2 队列 1.3 链表 1.3.1 单向链表 1.3.2 双向链表 1.4 栈 2. 非线性数据结构 2.1 树 2.2 二叉树 2.2.1 概念介绍 2.2.2 遍历操作 2.2.3 删除节点 2.2.4 查找局限性 2.2.5 AVL&#xff08; …

linux kernel 内存踩踏之KASAN_SW_TAGS(二)

一、背景 linux kernel 内存踩踏之KASAN&#xff08;一&#xff09;_kasan版本跟hasan版本区别-CSDN博客 上一篇简单介绍了标准版本的KASAN使用方法和实现&#xff0c;这里将介绍KASAN_SW_TAGS和KASAN_HW_TAGS 的使用和背后基本原理&#xff0c;下图是三种方式的对比&#x…

Ps:焦点堆栈

焦点堆栈 Focus Stacking是一种摄影和图像处理技术&#xff0c;通过合并多张在不同焦距拍摄的照片来创建一张具有更大景深的图像&#xff0c;特别适用于微距摄影、风景摄影和任何需要在整个场景中保持尖锐对焦的情况。 ◆ ◆ ◆ 拍摄注意事项 1、使用三脚架 为了确保图像之间…

【Node-RED】安全登陆时,账号密码设置

【Node-RED】安全登陆时&#xff0c;账号密码设置 前言实现步骤密码生成setting.js 文件修改 安全权限 前言 Node-RED 在初始下载完成时&#xff0c;登录是无账号密码的。基于安全性考虑&#xff0c;本期博文介绍在安全登陆时&#xff0c;如何进行账号密码设置。当然&#xff…

git相关内容

一.git安装 该操作相信不用介绍了&#xff0c;为什么用yum&#xff0c;大家也是非常清楚的。 如果是root账户&#xff1a;yum -y install git 如果是普通账户&#xff1a; sudo yum -y install git 二.git和gitee/github区别 Git&#xff08;读音为/gɪt/&#xff09;是一个…

CDP和Chrome

CDP和Chrome CDP和WebDriver Protocol WebDriver和 Chrome DevTools Protocol&#xff08;CDP&#xff09; 是用于自动化浏览器的两个主要协议&#xff0c;大多数的浏览器自动化工具都是基于上述其中之一来实现的。可以通过这两种形式来和浏览器交互&#xff0c;通过代码来控…

语义分割-基础知识

1.cls_iou计算: cls0_iou预测正确的像素个数/&#xff08;预测为该类别的像素个数真实标签为该类别的像素个数-预测正确的像素个数&#xff09; mean_iou各个类别的像素预测准确值相加/像素总个数2.转置卷积(Transposed Convolution) 转置卷积不是卷积的逆运算 转置卷积也是卷…