计算机程序在存储数据时必须跟踪的3种基本属性:
- 信息存储在何处
- 存储的值为多少
- 存储的信息是什么类型
对变量使用地址运算符(&),就可以获得它的位置
*
运算符被称为间接值(indirect value)或解除引用(dereferencing)运算符,将其应用于指针,可以得到该地址处存储的值
声明和初始化指针
下面的声明创建一个指针(p1)和一个int变量(p2):
int* p1, p2;
对每个指针变量名,都需要使用一个*
指针的危险
在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。
一定要在指针应用解除引用运算符
*
之前,将指针初始化为一个确定的、适当的地址。
指针和数字
- 不能简单地将整数赋给指针:
int * pt;
pt = 0xB8000000; // type mismatch
- 应通过强制类型转换将数字转换为适当的地址类型:
int * pt;
pt = (int *) 0xB8000000; // types now match
使用new来分配内存
指针真正的用武之地在于,在运行阶段分配未命名的内存以存储值。
new将找到一个长度正确的内存块,并返回该内存块的地址。
int * pn = new int;
new分配的内存块通常与常规变量声明分配的内存块不同。变量nights和pd的值都存储在被称为栈(stack)的内存区域中,而new从被称为堆(heap)或自由存储区(free store)的内存区域分配内存。
使用delete释放内存
使用delete时,后面要加上指向内存块的指针(这些内存块最初是用new分配的):
int * ps = new int; // allocate memory with new
. . .
delete ps; // free memory with delete when done
这将释放ps指向的内存,但不会删除指针ps本身。一定要配对地使用new和delete;否则将发生内存泄漏(memory leak)。
不要尝试释放已经释放的内存块;不能使用delete来释放声明变量所获得的内存。
只能用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的。
使用new来创建动态数组
通常,对于大型数据(如数组,字符串和结构),应使用new。
- 使用new创建动态数组
int * psome = new int [10]; // get a block of 10 ints
. . .
delete [] psome; // free a dynamic array
new运算符返回第一个元素的地址。
方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素。
使用new和delete时,应遵守以下规则。
1.不要使用delete来释放不是new分配的内存。
2.不要使用delete释放同一个内存块两次。
3.如果使用new []为数组分配内存,则应使用delete []来释放。
4.如果使用new []为一个实体分配内存,则应使用delete(没有方括号)来释放。
5.对空指针应用delete是安全的。
使用动态数组
数组和指针基本等价是C和C++的优点之一。
只要把指针当数组名使用即可。
将指针加1后,它将指向下一个元素。
psome = psome + 1;
//psome[0]现在指的是数组的第2个值
double wages[3] = {10000.0, 20000.0, 30000.0};
//和所有数组一样,wages也存在下面的等式
wages = &wages[0] = address of first element of array
将指针变量加1后,其增加的值等于指向的类型占用的字节数。
arrayname[i] becomes *(arrayname + i)
pointername[i] becomes *(pointername + i)
在很多情况下,可以相同的方式使用指针名和数组名。对于它们,可以使用数组方括号表示法,也可以使用解除引用运算符(*)。在多数表达式中,它们都表示地址。区别之一是,可以修改指针的值,而数组名是常量。
另一个区别是,对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度
在C++中,用引号括起的字符串像数组名一样,也是第一个元素的地址