第 4 章 复合类型
4.1 数组
只有在声明时才可以初始化,语法为 int ages[4] = {6, 8, 10, 12}
。
如果只对数组的一部分初始化,则其余部分都会被初始化为 0。
C++11 的数组初始化允许省略等号,在大括号中也可以不包含任何东西,这样也可以使数组初始化为全 0 数组。
4.2 字符串
以空字符 \0
结尾的 char 数组才可以被认为是字符串。
初始化方法有 char[8] name = {'A', 'l', 'i', 'c', 'e', '\0'}
或 char[] name = "Alice"
。
如果字符串长度大于声明的字符数目,则其余的元素都将被自动设置为 \0
。
strlen()
方法只计算可见字符,而不考虑 \0
。
get()
函数保留换行符在队列中,而 getline()
不保留,因此 getline(name, 8)
和 get(name, 8).get()
等价。
使用 cin >>
时会将换行符保留在输入队列中,继续读取时需要先丢弃该换行符。
4.3 string
类简介
string
可以将对象声明为简单变量,使用等号赋值。
处理 string
对象的语法比 C 风格字符串函数简单,而且可以自动调整大小。
strcpy()
和 strcat()
分别用于复制和连接 C 风格字符串,但可能会导致目标数组过小无法存储信息的问题,使用 strncpy()
和 strncat()
可以避免这种问题发生。
C++11 新增原始字符串,字符表示的就是它自己而无视转义字符,表示方法为 R"(I am text)"
,也可以更换定界符表示为 R"+*(I am text)+*"
,即 R"定界符(内容)定界符"
。
4.4 结构简介
C++ 允许在声明结构变量时省略关键字 struct
。
初始化时将结构中每个成员值使用逗号分隔,并使用花括号分开。
4.5 共用体
用于节省内存,常用于操作系统数据结构或硬件数据结构。
4.6 枚举
默认情况下,第一个枚举量的值为 0。
尽管没有为枚举本身定义算术运算,但在有的实现方法中没有这种限制。
可以显示地设置枚举量的值,也可以创建多个值相同的枚举量。
可以将任何整数值赋给枚举变量,即使这个值不是枚举值。
4.7 指针和自由存储空间
int* p1, p2;
语句创建了一个指针和一个 int
变量。
long *fellow; *fellow = 1200;
可能隐含存在的问题:没有初始化 fellow
的值,它可能在任何位置,即使是已占用的地址,因此在使用 *
解除引用运算符前,一定要把指针初始化为一个确定的、合适的地址。
为一个数据对象获得并指定分配内存的方法为 typeName *pointer_name = new typeName
。
常规变量声明存储在称为栈的内存区域中,而 new
从被成为堆或自由存储区的内存区域分配内存。
一定要配对地使用 new
和 delete
以免发生内存泄漏。
如果使用 new []
为数组分配内存,则也应该使用 delete []
来释放。
通过声明创建数组属于静态联编,数组大小固定。使用 new
可以实现动态联编,数组长度可以在运行时决定。
C++ 中数组和指针基本等价,可以直接将指针当作数组名使用。
4.8 指针、数组和指针算数
将指针变量加 1 后,其增加的值等于指向的类型占用的字节数。
允许 pointerName = pointerName + 1
但不允许 arrayName = arrayName + 1
。
tacos[3]
等于 *(tacos + 3)
等于在 tacos + 3
地址的值,负数同样适用。
在多数 C++ 表达式中,char
数组名、char
指针以及用引号包围的字符串常量都被解释为字符串第一个字符的地址。
指定结构成员时,结构名使用 .
,结构的指针使用 ->
。
函数内部定义的常规变量使用自动存储空间,被称为自动变量,函数结束后自动消亡,通常存储在栈中。在函数外定义或声明时使用了关键字 static
时的变量称为静态变量,存在于程序的整个生命周期。new
和 delete
管理了一个内存池,也称为自由存储空间或堆,生命周期不受程序或函数生命周期控制。
4.9 类型组合
4.10 数组的替代品
array
对象和数组存储在栈中,vector
对象存储在堆中。