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

3.5 数组

数组是一种类似于标准库类型vector的数据结构,与vector相似的地方是,数组也是存放类型相同的对象的容器,不同的是,数组的大小确定不变,不能随意向数组中添加元素。

3.5.1 定义和初始化内置数组

数组是一种复合类型,数组的声明形如a[d],其中a是数组的名字,d是数组的维度(数组中元素的个数),编译时维度必须是已知的,即维度必须是一个常量表达式。定义数组时必须指定数组的类型,不允许用auto关键字推断类型。
显式初始化数组元素
可以对数组的元素进行列表初始化,此时可以忽略数组的维度。如果指明了维度,则初始值的总数量不应该超过指定的大小,若超过,则初始值初始化靠前的元素,剩余的元素被初始化为默认值。

字符数组的特殊性
字符数组可以用字符串字面值进行初始化,注意字符串字面值的结尾处有一个空字符,也会拷贝到字符数组中。如下图中a3的维度为4.

不允许拷贝和赋值
不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

理解复杂的数组声明

注意:定义在函数体内部的内置类型将不被初始化,其值是未定义的,如果试图拷贝或者访问此类值将引发错误。同样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值。

3.5.2 访问数组元素

数组的元素可以用范围for语句或下标运算符来访问,数组的索引从0开始,在使用数组下标的时候,通常将其定义为size_t类型。当需要遍历数组的所有元素时,最好的办法是使用范围for语句。

3.5.3 指针和数组

对数组的元素使用取地址符就能得到指向该元素的指针。

在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针。string *p2 = nums; 这里的p2和上面的p是相同的,都是指向首元素的指针。在大多数表达式中,使用数组类型的对象其实就是使用一个指向该数组首元素的指针。
数组的操作实际上就是指针的操作。当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组。当使用decltype关键字时,返回的类型仍是数组。
在这里插入图片描述
指针也是迭代器
vector和string的迭代器支持的运算,数组的指针全都支持。例如,允许使用递增运算符将指定数组元素的指针向前移动到下一个位置:

使用指针也可以便利数组中的元素,通过数组名或者首元素的地址可以得到指向首元素的指针,要获取尾后指针,就是获取数组尾元素之后的那个并不存在的元素的地址,使用:int *e = &arr[10]; // 指向arr尾元素的下一个位置的指针。类似于迭代器,由首元素指针和尾后指针,便可以循环遍历所有元素。

标准库函数begin和end
尽管能计算得到尾后指针,但这种用法极易出错,C++11引入begin和end函数,用法如下:

注意,尾后指针不能执行解引用和递增操作。
指针运算
指向数组元素的指针可以执行所有的迭代器运算(详见迭代器那一节),和用在迭代器上的意义完全一致。两个指针相减的结果的数据类型是一种名为ptrdiff_t的标准库类型。
解引用和指针运算的交互
指针加上一个整数所得的结果还是一个指针。假设结果指针指向了一个元素,则允许解引用该结果指针以获得指针所指的元素。
下标和指针
对数组执行下标运算其实是对指向数组元素的指针执行下标运算。

标准库类型限定使用的下标必须是无符号类型,而内置的下标运算符所用的索引值不是无符号类型可以为负值。

3.5.4 C风格字符串

字符串字面值是一种通用结构的实例,这种结构即是C++由C继承而来的C风格字符串。C风格字符串不是一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法。按此习惯书写的字符串存放在字符数组中并以空字符结束。
C标准库String函数
C语言标准库提供了一组函数,用于操作C风格字符串。定义在cstring头文件中。C风格字符串只能用这些函数,不能用类似于标准库string的操作。

使用标准库string要比使用C风格字符串更安全、更高效。
使用指针和数组很容易出错。现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;应该尽量使用string,避免使用C风格的基于数组的字符串。

3.6 多维数组

C++语言中没有多维数组,通常所说的多维数组其实是数组的数组。当一个数组的元素仍然是数组时,通常使用两个维度来定义它:一个维度表示数组本身大小,另外一个维度表示其元素(也是数组)的大小。
多维数组初始化
使用花括号括起来的一组值初始化多维数组。

其中内层嵌套着的花括号并非必需的。在初始化多维数组时也并非所有元素的值都必须包含在初始化列表之内,其他未列出的元素执行默认值初始化。
多维数组的下标引用
可以使用下标运算符来访问多元数组的元素。如果下标运算符数量和数组的维度一样多,结果是给定类型的元素;如果下标运算符数量小于数组维度,则结果为给定索引处的内层数组。经常用到两层嵌套的for循环来处理多维数组的元素。
使用范围for语句处理多维数组
在这里插入图片描述
第一个for循环遍历ia的所有元素,row的类型是含有4个整数的数组的引用;第二个for循环遍历那些4元素数组中的某一个,col的类型是整数的引用。
要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制控制变量都应是引用类型,避免数组被自动转化为指针。
指针和多维数组
多维数组实际上是数组的数组,所以有多维数组名转化得来的指针实际上是指向第一个内层数组的指针。

(*p)意味着p是一个指针,括号必不可少。
通过使用auto或者decltype就能尽可能地避免在数组前面加上指针类型了。

指针p指向ia的第一个内层数组,*p是一个含有4个整数的数组,数组名转化为首元素指针,故指针q指向p所指数组的第一个元素。也可以使用标准库函数begin和end实现同样的功能。

类型别名简化多维数组的指针
读、写和理解一个指向多维数组的指针是一个让人不胜其烦的工作,使用类型别名能让这项工作变得简单一点。
在这里插入图片描述
这里int_array *p 等价之前的 int (*p)[4],表示指向4个整数数组的指针。

发布了16 篇原创文章 · 获赞 11 · 访问量 646

猜你喜欢

转载自blog.csdn.net/qq_42820853/article/details/104477263
今日推荐