C++基础系列三:数组
C++语言提供了两种类似于vector和迭代器类型的低级复合类型——数组和指针(此话出自C++Primer 中文版第四版P109,总觉这话让人看着不舒服……),设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。
数组元素可以是引用外的任何内置类型或者类类型。
(1)数组的初始化
在没有显示初始化的情况下,数组元素的初始化类似于普通变量:
a. 在函数体外(全局)的定义的内置数组,其元素均初始化为0;
b. 在函数体内定义的内置数组,其元素无初始化;
c. 如果为类类型,不管在哪里定义,都自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显示初始化。
显示初始化的数组不需要指定数组的维数值,编译器会根据列出的元素个数确定数组的长度。
如果指定的数组维数超过了初始化列表里的元素个数,那么剩下的元素若是内置类型就初始化为0,若是类类型就调用该类的默认构造函数进行初始化。
(2)字符数组
字符数组可以用一个字符串字面值进行初始化,也可以用一组花括号括起来、逗号隔开的字符字面值进行初始化,两者的区别是前者包含一个额外的null用于结束字符串,后者则不包含,除非显示包含。如:
1 char ca1[] = {'C', '+', '+'};// not null 2 char ca2[] = {'C', '+', '+', '\0'};//explicit null 3 char ca3[] = "C++";//null added automatically
(3)数组不能直接复制和赋值
一个数组不能用另一个数组初始化,也不能将一个数组赋值给另一个数组。
但是,C++允许使用数组初始化vector对象,使用这种方法时,必须指出用于初始化式的第一个元素以及数组最后一个元素的下一个位置的地址,如下面的语句将数组的所有元素都用来初始化vector<int>对象ivec:
const size_t arr_size = 6; int arr[arr_size] = {0, 1, 2, 3, 4, 5}; vector<int> ivec(arr, arr+arr_size);
补充:数组的下标类型为size_t,string和vector类类型用size_type作为下标类型。size_t是在cstddef头文件中定义的机器相关的无符号整型,该类型足以保存最大数组的长度;size_type用以保存任意string对象或vector对象的长度,标准库类型将size_type定义为unsigned类型。
(4)动态数组
动态分配的数组不必在编译时知道其长度,可以在运行时才确定数组长度。与数组变量不同,动态分配的数组一直存在,内存空间位于堆,直到程序释放它为止。
初始化:动态分配数组时,如果数组元素具有类类型,将使用该类的默认构造函数进行初始化,如果数组元素是内置类型,则无初始化而不管它是在函数体外还是在函数体内。
可以通过在数组长度后面加一对空圆括号来对数组元素做值初始化,如:
int *a = new int[10]();
C++不允许定义长度为0的数组变量,但允许调用new创建长度为0的数组是合法的,如:
char ca[0];//error:cannot define zero-length array char* cp = new char[0];//ok
动态数组的释放必须在delete和数组名之间添加[],否则编译器检测不出错误,但会造成运行时错误。