指针是一种允许我们对计算机内存进行更多控制的结构。用变量起始处的内存地址来命名该变量,改地址就称为指针。
1. 指针变量
(a) 如果一个变量需要容纳指针,而且这个指针指向Type_Name类型的其它变量。那么在声明指针变量是,需要采用和声明Type_Name类型的普通变量相似的方式,不同的是必须在变量名之前添加一个星号。
语法
Type_Name *Variable_Name1, *Variable_Name2,...;
实例:
double *pointer1, *pointer2;
(b) 地址和数字:
指针是地址,而地址是整数,但指针不是整数。C++坚称指针要作为地址使用,不能作为数字使用。指针不是int类型或者其它任何类型的一个数值。通常不能将指针变量存储到int类型的变量中,如果你坚持这样做,大多数C++编译器会报错。另外不能对指针执行标准的算术运算(虽然能对指针执行某种形式的加减操作,但他们并不是普通的整数加减)。
(c) 操作符*和&
指针变量前的操作符*生成它所指向的变量。像这样使用*操作符称作为提领操作符(dereferenced operator)。普通变量前的的操作符&生成那个变量的地址;换言之,它生成的是一个指向变量的指针。操作符&简单地称为取址(address-of)操作符。
例如:
double *p , v;
以下语句会设置p的值,使p指向v:
p = &v;
*p则生成(提领)由p指向的那个变量,所以在指行上述赋值语句之后,*p和v引用了同一个变量。例如,以下语句会将v值设为99.9,即使其中根本没有出现v的名称:
*p = 99.9;
(d) 操作符new
操作符new创建指定类型的一个新的动态变量,返回指向这个新变量的指针。
int *p;
p = new int;
如果类型是一个带有构造函数的类,会为新建的动态变量调用默认构造函数。也可以指定初始化列表,从而调用其它函数版本:
int *n;
n = new int(17);//将n初始化为17
MyType = mtPtr;
mtPtr = new MyType(32.0,17);//调用MyType(double,int)
C++标准规定,若没有足够的内存来创建新变量,操作符new默认会终止程序。
2. 基本内存管理
系统会为动态变量保留一个特殊的存储区域,它称之为自由存储(freestore)。程序创建的任何变量都会消耗自由存储中的部分内存。操作符delete可销毁一个动态变量,并将动态变量占用的内存还给自由存储,是内存得以重用。这样就可以重用那些内存来创建新的变量。
delete p;
像这样调用delete之后,指针变量(比如p)的值就会变成未定义。
3. 虚悬指针
delete之后的指针变量的值进入未定义状态,这些未定义的指针变量称为虚悬指针。将一个提领操作符(*)作用于p(生成表达式*p),将产生不可预料的后果。
常用做法:
delete p;
p = NULL;
4. 静态变量和自动变量
使用new操作符创建的变量称为动态变量,因为他们是在程序运行时创建和销毁的。
自动变量:在main或其它函数定义中声明的变量,它们的动态属性是由系统控制的;
普通变量:调用一个函数时,函数内部声明的变量会自动创建,函数调用结束之后,它们会被自动销毁,通常将这些变量称为普通变量(有时候也成为自动变量);
全部变量:在任何函数定义(包括main函数)的外部声明的变量。
5. 定义指针类型
typedef为“任何类型名称或者定义”定义一个别名。这些类型定义通常放在程序main主体的外部(以及其它函数主体的外部),和struct和类定义位于同一个级别上。
例如:
typedef int* IntPtr;
int *p;
等价于
IntPtr *p;
定义函数时,如果将一个指针变量作为传应用调用参数使用,将体现出已定义指针类型的第二个好处,如果不利用已定义的指针类型,就需要在函数声明中同时利用到符号&和*,这样很容易困惑:
void sampleFunc(IntPtr pointer_Variable);