一、数组
C++虽然不允许定义长度为0的数组变量,但明确指出,调用new动态创建长度为0的数组是合法的。
- 在函数体外定义的内置数组,其元素均初始化为0;
- 在函数体内定义的内置数组,其元素无初始化,其值是不确定的;
- 不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显式初始化。
3. 特殊的字符数组
字符数组既可以用一组由花括号括起来、逗号隔开的字符字面值进行初始化,也可以用一个字符串字面值进行初始化。
字符串字面值包含一个额外地空字符(null)用于结束字符串。
当使用字符串字面值来初始化创建的新数组时,将在新数组中加入空字符:
1 char ca1[] = {'C' , '+' , '+'}; // no null 2 char ca2[] = {'C' , '+' , '+' , '\0'}; //explict null 3 char ca3[] = "C++"; // null terminator added automatically
ca1的维数是3,而ca2和ca3的维数则是4.使用一组字符字面值初始化字符数组时,一定要记得添加结束字符串的空字符。
4、数组元素也是从0开始计数,vector中使用vector::size_type作为下标类型,在数组中下标的正确类型是size_t。
1 const size_t array_size = 10; 2 intg ia[array_size]; 3 for(size_t ix=0; ix != array_size; ++ix) 4 ia[ix] = ix;
5、导致安全问题的最常见原因是所谓的“缓存区溢出(buffer overflow)”错误,当没有检测下标引用了越出数组或者其他类似数据结构边界时容易出现这个错误。
二、指针
- 0值常量表达式
- 类型匹配的对象的地址
- 另一个对象之后的下一个地址
- 同类型的另一个有效指针
5.具有void* 类型的指针可以保存任意类型对象的地址。
指针操作
- int ival = 1023;
- int *pi = &ival;
- int **ppi = π
- int ia[] = {0,2,4,6,8};
- int i = ia[0];
- int *p = &ia[2]; //ok:p points to the element indexed by 2
- int j = p[1]; //p[1] == ia[3] ,ok:p[1] equivalent to *(p + 1) , p[1] is the same element as ia[3]
- int k = p[-2]; //p[-2] == ia[0] ok:p[-2] is the same element as ia[0]
ptrdiff_t n = ip2 - ip; // ok:distance between the pointers
11. C字符串的标准库函数
12.永远不要忘记字符串结束符null
在使用处理C风格字符串的标准库函数时,牢记字符串必须以结束符null结束:
1 char ca[] = {'C' , '+' , '+'}; // not null-terminated 2 cout<< strlen(ca)<<endl; // disaster: ca is not null-terminated
在这个例题中,ca是一个没有null结束符的字符数组,则计算的结果不可预料。
标准库函数strlen总是假定其参数字符串以null字符结束,当调用该标准库函数时,系统将会从实参ca指向的内存空间开始一直搜索结束符,知道恰好遇到null位置。strlen返回这一段空间中总共有多少个字符,无论如何这个数值不可能是正确的。
1 //用int型数组初始化vector对象 2 3 //输入数组元素 4 for(size_t ix = 0 ; ix != arr_size ; ++ix) 5 cin >> int_arr[ix]; 6 //用int型数组初始化vector对象 7 vector<int> ivec(int_arr , int_arr + arr_size);
三、创建动态数组
- int *pia = new int[10]; // array of 10 uninitialized ints
- string *psa = new string[10] ; // 定义10个空string的数组
- int *pia = new[10]; // 定义10个未初始化的int数组
- delete []pia; //该语句回收pia所指向的数组,把相印的内存返还给自由存储区。