题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。
数组的维数必须用值大于等于1的常量表达式定义。
如果指定了数组维数,那么初始化列表提供的元素个数不能超过维数值。如果维数值大于列表中的元素个数,则只初始化前面的数组元素;对于剩下的元素,若是内置类型则初始化为0,若是类类型则调用其默认构造函数进行初始化。
动态创建数组
动态创建数组时,不能进行初始化,但却可以用值初始化()要求编译器把内置类型初始化为0。另外,C++允许动态分配长度为0的数组。动态数组的释放一定要记得用delete []。例如:
string* psa = new string[10]; // ok: array of 10 empty strings int* pia1 = new int[10]; // ok: array of 10 uninitialized ints int* pia2 = new int[10](); // ok: array of 10 initialized ints with value 0 int* pia3 = new int[10](3); // error: ISO forbids initializer
int* pia4 = new int[0]; // ok delete [] psa; delete [] pia1; delete [] pia2;
|
指针
指针的初始化和赋值
对指针进行初始化或赋值时,只能使用以下四种类型的值:
1)0常量表达式;
2)类型匹配的对象的地址;
3)另一对象末的下一个地址;
4)同一类型的另一个有效指针。
注意:把int型变量赋给指针是非法的,尽管此int型变量的值可能为0;C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用操作。而计算数组超出末端位置之后或数组之前的地址都是不合法的。
另外,还可以使用以C语言中继承而来的预处理变量NULL。该变量在头文件中定义,其值为0。个人倾向于使用NULL,这样更能直观地反映出是在对一个指针变量进行初始化或者赋值。注意:NULL是预处理变量,并不在std空间内。
指针的运算
两个指针相减的结果类型是ptrdiff_t类型,该类型在cstddef头文件中定义,并且是signed整型。
这里需要举一个例子:
typedef string* pstring;
const pstring cstr;
请问 cstr是什么类型?
这是一个很容易答错的问题。实质上cstr是一个string* 类型的const变量,即上面的定义相当于
string* const cstr;
因为声明const pstring cstr;时,const修饰的是pstring的类型,而不是修饰string类型。
数组与指针
在表达式中使用数组名时,该名字会自动转换成为指向数组第一个元素的指针。
建议: 尽量避免使用指针和数组:指针的错误使用(比如未初始化就使用)和数组越界是程序Bug的重要来源。相反,在C++程序里可以用vector类型和迭代器类型取代一般的数组和指针,采用string类型代替字符数组和C风格字符串。如果要使用指针,尽量在定义时初始化它。如果暂时不能初始化它,可以用0(NULL)作为它的初始值。一般的编译器都可以检查出值为0的指针的解引用。 |
多维数组
多维数组的初始化,其规则类似数组,因为多维数组实质上是数组的数组。这里只举个例子就能说明问题了,例如:
int ia[3][3] = {{1}, {2, 3}}; <===> int ia[2][3] = {{1, 0, 0}, {2, 3, 0}, {0, 0, 0}};
int ia[3][3] = {1, 2, 3}; <===> int ia[2][3] = {{1, 2, 3}, {0, 0, 0}, {0, 0, 0}};
同样因为多维数组是数组的数组,所以由多维数组转换而成的指针类型应是指向第一个内层数组的指针。因而,多维数组名将自动转换为指向该数组第一元素(也是数组)的指针。
当需要使用多维数组的指针时,可以使用typedef来简化定义这类指针,也使定义更加清晰直观。
最后,补充一下基本知识:
1)C风格字符串(C-style character string):以null('\0')结束的字符数组。
2)缓冲区溢出(buffer overflow):当程序中出现数组越界时,就会导致这类错误。
如果文中有错误或遗漏之处,敬请指出,谢谢!
参考文献:
[1] Thinking in C++(Volume Two, Edition 2)
[2] C++ Primer(Edition 4)
[3] International Standard:ISO/IEC 14882:1998