4.1 数组
- 编译器不会检查数组下标有效性,要确保下标不越界
- 列表初始化时注意不允许缩窄转换
4.2 字符串
cin 使用空白(空格、制表符和换行符)来确定字符串结束的位置,并自动在结尾添加空字符
4.2.4 每次读取一行字符串
-
getline()
默认通过换行符确定结尾,丢弃换行符并在结尾添加空字符’\0’,可以通过设置参数来改变换行符作为读入结束标志
在头文件istream和string中都有getline函数 -
get()
将换行符保留在缓冲队列中,下次读取输入队列时第一个就是换行符
cin.get(arry, n);
cin.get();
cin.get(arry, n).get();
4.4 结构
struct inflatable
{
char name[20];
float volume;
double price;
}
inflatable hat; // 可以省略 struct 关键字
struct inflatable hat;
4.4.6 结构中的位字段
C++和C一样,也允许指定占用特定位数的结构成员,这使得创建与某个硬件设备上的寄存器对应的数据结构非常方便。可以使用整型和按位运算符代替这种方法。
struct torgle_register
{
unsigned int SN : 4;
unsigned int : 4;
bool goodIn : 1;
bool goodTorgle : 1;
};
torgle_register tr = {14, true, false};
4.5 共用体 union
注意 union
和 struct
的字节对齐问题
4.6 枚举
- 利用 enum 创建符号常量可以代替 const
- 枚举是整型,可以提升为 int 类型,但是 int 类型不能自动转换为枚举类型
- 可以创建多个值相同的枚举
可以通过强制转换将一个在枚举取值范围的值赋给枚举变量
枚举取值范围:找到枚举量的最大值,则范围上限就是不小于最大值的最小二次幂的值减一,如果最小值不小于0,则范围下限就是0,如果最小值小于0,则按取上限的规则然后加上负号。
enum bigstep {first, second=100, third};
// third=101,则大于101的最小二次幂的数是 128=2^7,所以范围上限是 128-1=127
// 范围下限是 0
枚举类型占用的空间,一个或更少的字节,如果包含 long 类型,则使用4个字节
4.7 指针和自由存储空间
new/delete
和malloc/free
配对使用,避免内存泄露delete/free
之后将指针置为null
,避免成为野指针,再次尝试释放已经释放的空间,出现不可控的结果。但是对于空指针使用delete/free
是安全的
不能使用 sizeof
来确定动态分配的数组包含的字节数
数组的地址
关于一个数组的地址,有以下几种方式:
short tell[10];
cout << tell << endl;
cout << &tell << endl;
cout << &tell[0] << endl;
-
数值
三种形式在数值上是相等的 -
概念
tell
和&tell[0]
表示一个2字节内存块的地址&tell
表示的是整个数组,即一个20字节的内存块地址
tell + 1 地址值加 2(short) &tell + 1 地址值加 20
-
类型
tell
的类型是一个short
指针&tell
是一个指向还有20个元素的数组的指针(short(*)[20]
)
short (*pas)[20] = &tell; (*pas)[0] == tell[0] // 即(*pas)[0] 为 tell 的第一个元素 tell[0]
4.8 指针、数组和指针算术
4.8.5 自动存储、静态存储和动态存储
- 自动存储
函数内部定义的常规变量使用自动存储空间,成为自动变量。存储在栈中。
- 静态存储
使变量成为静态的方式有两种:函数外定义,或者使用关键字 static
- 动态存储
使用 new/delete ,在被称为自由存储空间或堆的内存池中。在栈中,自动添加和自动删除使得占用的内存总是连续的,但使用 new/delete 会产生存储区的碎片化,不连续。
内存泄露
如果没有使用 delete
释放通过 new
,申请的空间,那么即使指向内存的指针由于作用域规则和生命对象周期的愿意被释放,但是在自由存储区动态分配的空间依然存在,且因为指针的失效而无法访问,导致内存泄露。被泄露的内存在整个程序周期都无法是使用,无法被回收,极端情况下,内存泄露会导致程序的无法正常运行,内存耗尽。
4.10 数组的替代品
4.10.1 vector
类似 string 类,动态数组,可以设置长度或者自动调整长度,效率比数组低。
#include <vector>
vector<int> vi; // 长度为0
int n;
cin >> n;
vector<double> vd(n); // 长度为 n
vector<typeName> vt(n_elem);
n_elem 可以是整型变量
4.10.2 array
与数组相同,但是更加安全,更方便。
#include <array>
array<int, 5> ai;
array<double, 4> ad = {1.2, 2.1, 3.4, 4.3};
array<double, 4> ap;
ap = ad; // 大小相同的 array 可以 赋值
array<typeName, n_elem> arr;