<基于 C++ Primer P101>
内置数组类型和其他内置类型一样,其实现与硬件密切相关,体现了大多数计算机硬件本身具备的能力。因此相较于标准库类型 string 和 vector,在灵活性上稍显不足。
1.定义和初始化
数组在编译时维度应是已知的,即必须是一个常量表达式。
unsigned cnt = 42; // 不是常量表达式
constexpr unsigned sz = 42; // 常量表达式
int arr[10]; // 正确
int *parr[sz]; // 正确
string bad[cnt]; // 错误
string strs[get_size()]; // 若 get_size 是 constexpr 正确,否则错误
定义数组时不允许使用 auto 关键字,也不存在引用的数组。
(1)显式初始化
const unsigned sz = 3;
int ia1[sz] = {0, 1, 2}; // 正确
int a2[] = {0, 1, 2}; // a2[] 的维度是 3
int a3[5] = (0, 1, 2}; // a3[] = {0, 1, 2, 0, 0}
string a4[3] = {"hi", "bye"}; // a4[] = {"hi", "bye", " "}
int a5[2] = {0, 1, 2}; // 错误:初始值过多
int a6[3] = {0}; // a6[0] = 0, 其余元素被值初始化为 0
(2)字符数组
可以使用字符串字面值初始化,注意考虑结尾的空字符。
char a1[] = {'C', '+', '+'}; // 列表初始化,无空字符
char a2[] = {'C', '+', '+', '\0'}; // 列表初始化,有空字符
char a3[] = "C++"; // 自动添加空字符
const char a4[6] = "Daniel"; // 错误:没有空间可以存放空字符
(3)不允许拷贝和赋值
int a[] = {0, 1, 2};
int a2[] = a; // 错误
a2 = a; // 错误
(4)复杂的数组声明
先分析括号内,随后从右向左一次绑定。
int *ptrs[10]; // 含有 10 个指针的数组
int &refs[10] = /*?*/ // 错误,不存在引用的数组
int (*Parray)[10] = &arr; // Parry 指向一个含有 10 个整数的数组
int (&arrRef)[10] = arr; // arrRef 引用一个含有 10 个整数的数组
int *(&arry)[10] = ptrs; // arry 是数组的引用,该数组含有 10 个指针
2.访问数组元素
可以使用下标运算符来访问,索引从0开始。
使用数组下标时,通常定义为 size_t 类型。
需要遍历数组的所有元素时,最好使用范围for语句。
注意检查下标的值,0 ≤ 下标 < 数组大小。