一些有可能会“冷不丁”出现的数组知识
一、使用数组初始化 vector 对象
不能用一个数组直接初始化另一数组,程序员只能创建新数组,然后显式地把源数组的元素逐个复制给新数组。
这反映 C++ 允许使用数组初始化 vector 对象,尽管这种初始化形式起初看起来有点陌生。
使用数组初始化 vector 对象,必须指出用于初始化式的第一个元素以及数组最后一个元素的下一位置的地址:
1 const size_t arr_size = 6; 2 int int_arr[arr_size] = {0, 1, 2, 3, 4, 5}; 3 // ivec has 6 elements: each a copy of the corresponding element in int_arr 4 vector<int> ivec(int_arr, int_arr + arr_size);
传递给 ivec 的两个指针标出了 vector 初值的范围。第二个指针指向被复制的最后一个元素之后的地址空间。
当然,被标出的元素范围可以是数组的子集:
1 // copies 3 elements: int_arr[1], int_arr[2], int_arr[3] 2 vector<int> ivec(int_arr + 1, int_arr + 4);
这个初始化创建了含有三个元素的 ivec,三个元素的值分别是 int_arr[1] 到 int_arr[3] 的副本。
二、多维数组
严格地说,C++ 中没有多维数组>_<|||,通常所指的多维数组其实就是数组的数组:
如果表达式只提供了一个下标,则结果获取的元素是该行下标索引的内层数组。
与普通数组一样,使用多维数组名时,实际上将其自动转换为指向该数组第一个元素的指针。
因为多维数组其实就是数组的数组,所以由多维数组转换而成的指针类型应是指向第一个内层数组的指针。
尽管这个概念非常明了,但声明这种指针的语法还是不太容易理解:
1 int ia[3][4]; // array of size 3, each element is an array of ints of size 4 2 int (*ip)[4] = ia; // ip points to an array of 4 ints 3 ip = &ia[2]; // ia[2] is an array of 4 ints
定义指向数组的指针与如何定义数组本身类似:首先声明元素类型,后接(数组)变量名字和维数。
窍门在于(数组)变量的名字其实是指针,因此需在标识符前加上 *。
如果从内向外阅读 ip 的声明,则可理解为:*ip 是 int[4] 类型——即 ip 是一个指向含有 4 个元素的数组的指针。
用 typedef 类型定义能够简化指向多维数组的指针。
以下程序用 typedef 为 ia 的元素类型定义新的类型名:
1 typedef int int_array[4]; 2 int_array *ip = ia;
可使用 typedef 类型输出 ia 的元素:
1 for (int_array *p = ia; p != ia + 3; ++p) 2 for (int *q = *p; q != *p + 4; ++q) 3 cout << *q << endl;
外层的 for 循环首先初始化 p 指向 ia 的第一个内部数组,然后一直循环到 ia 的三行数据都处理完为止。
++p 使 p 加 1,等效于移动指针使其指向 ia 的下一行(例如:下一个元素)。
内层的 for 循环实际上处理的是存储在内部数组中的 int 型元素值。
首先让 q 指向 p 所指向的数组的第一个元素。对 p 进行解引用获得一个有 4 个 int 型元素的数组,
通常,使用这个数组时,系统会自动将它转换为指向该数组第一个元素的指针。
在本例中,第一个元素是int型数据,q指向这个整数。系统执行内层的 for 循环直到处理完当前 p 指向的内部数组中所有的元素为止。
当 q 指针刚达到该内部数组的超出末端位置时,再次对 p 进行解引用以获得指向下一个内部数组第一个元素的指针。
在 p 指向的地址上加 4 使得系统可循环处理每一个内部数组的 4 个元素。