C++ 语言提供了两种类似于 vector 和迭代器的低级复合类型——数组和指针。有以下几点要注意:
- 现代 C++ 程序应尽量使用 vector 和迭代器类型,而避免使用低级的数组和指针。现代 C++程序采用 vector类型和迭代器取代一般的数组、采用 string 类型取代 C 风格字符串。
- 与 vector 类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个给定数组的长度。
- 与 vector 不同,一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组。
- 指针是指向某种类型对象的复合数据类型,是用于数组的迭代器。
1、定义指针的语法
定义指针变量时,允许把string和* 写在一起,如:
string* ps1, ps2;
此时,实际上只把 ps1 定义为指针,而 ps2 并非指针,只是一个普通的 string对象而已。当然更通常的做法是
string *ps1,*ps2;
2、指针和引用的比较
虽然使用引用和指针都可间接访问另一个值,但它们之间有两个重要区别。
第一个区别在于引用总是指向某个对象,定义引用时没有初始化是错误的。
第二个重要区别则是赋值行为的差异:给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。
3、指向指针的指针
int ival = 1024;
int *pi = &ival; // pi points to an int
int **ppi = π
定义了指向指针的指针。C++ 使用 ** 操作符指派一个指针指向另一指针。为了真正地访问到 ival 对象,必须对 ppi 进行两次解引用。
4、指针和 const 限定符
一、指向 const 对象的指针
const double *cptr;
不能通过解引用 修改 所指向对象的值,即使该对象本身并不是const的。
二、const 指针
int errNumb = 0;
int *const curErr = &errNumb;
const 指针的值不能修改,这就意味着不能使 curErr 指向其他对象。与任何 const 量一样,const 指针也必须在定义时初始化。当然,指针所指对象的值能否修改完全取决于该对象的类型。
三、指向 const 对象的 const 指针
const double pi = 3.14159;
// pi_ptr is const and points to a const object
const double *const pi_ptr = π
本例中,既不能修改 pi_ptr 所指向对象的值,也不允许修改该指针的指向(即 pi_ptr 中存放的地址值)。
5、C 风格字符串
其实,字符串字面值的类型就是const char 类型的数组,而且是以空字符 null 结束的字符数组。
尽管 C++ 支持 C 风格字符串,但不应该在 C++ 程序中使用这个类型。C 风格字符串常常带来许多错误,是导致大量安全问题的根源。
6、动态数组
每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为 程序的自由存储区或堆 。C 语言程序使用一对标准库函数malloc 和 free 在自由存储区中分配存储空间,而 C++ 语言则 使用 new 和delete 表达式实现相同的功能。
一、动态数组的定义
动态分配数组时,只需指定类型和数组长度,不必为数组对象命名,new 表达式返回指向新分配数组的第一个元素的指针:
int *pia = new int[10];
此 new 表达式分配了一个含有 10 个 int 型元素的数组,并返回指向该数组第一个元素的指针,此返回值初始化了指针 pia。
C语言中,也可以用malloc来动态定义数组
int *a=(int *)malloc(n*sizeof(int));//定义动态数组 相当于int a[n]
二、动态空间的释放
delete [] pia;
该语句回收了 pia 所指向的数组,把相应的内存返还给自由存储区。在关键字 delete 和指针之间的 空方括号对是必不可少的: 它告诉编译器该指针指向的是自由存储区中的数组,而并非单个对象。
7、使用数组初始化 vector 对象
使用数组初始化 vector 对象, 必须指出用于初始化式的第一个元素以及数组最后一个元素的下一位置的地址:
const size_t arr_size = 6;
int int_arr[arr_size] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(int_arr, int_arr + arr_size);
8、指针和多维数组
int *ip[4]; // ip是一个含有4个指向int指针的数组名
int (*ip)[4]; // ip 是一个指向含有 4 个元素的数组的指针。
用 typedef 简化指向多维数组的指针
首先弄清typedef的用法。我们先定义一个string类型的指针变量
string *str1;
这里str1是变量名。如果把这句话前面加上一个typdef,也就是
typedef string *str2;
这时str2就不是变量名,而是类型名,它的类型就是变量str1所具有的类型。也就是string *类型。这样以后就可以拿pstring去定义别的变量
pstring pstr;
这就定义了一个指向string的指针对象pstr。
下面来看用typedef对多维数组的简化。假设有
int ia[3][4];
这里ia就是一个三行四列的二维数组。
接着看这么一句:
typedef int int_array[4];
如果去掉前面的typedef,那么定义的是一个叫做int_array的含有4个元素的数组。前面加上typedef以后,int_array就变成了含有4个元素的数组类型的替代名。于是对于
int_array *p=ia;
我们知道它等同于
int (*p)[4]=ia;
这里p是一个指向含有 4 个整型元素的数组的指针。*p是ia第1行第1个元素的地址。