概述
指针基本上和其它的变量一样,唯一的一点不同就是指针并不包含实际的数据,而是包含了一个指向内存位置的地址,你可以在这个地址找到某些信息。这是一个很重要的概念,并且许多程序或者思想都是将指针作为它们的设计基础,例如链表。
定义一个指针,需要在变量名之前添加一个星号。例如,下面的代码创建了指向整数的指针:
int* pNumberOne;
变量名的前缀“p”用来表示这个变量是一个指针。
pNumberOne=&some_number;
“&”标志读作“the address of(……的地址)”,作用是返回一个变量的内存地址,而不是这个变量本身。
如果希望由pNumberOne而使用some_number的值,可以用*pNumberOne。“*”读作“the memory location pointed to by(由……指向的内存位置)”,它用来取得指针所指向的值。不过指针声明的情况例外,如“int*pNumber”。 见下例:
#include
void main()
{
int nNumber;
int*pPointer;
nNumber= 15;
pPointer=&nNumber;
printf("nNumber is equal to:%d\n", nNumber); //=15
*pPointer= 25;
printf("nNumber is equal to:%d\n", nNumber); //=25
}
内存的动态分配
动态分配是指针的关键技术。它用于在没有定义变量的情况下分配内存,然后由一个指针指向这段内存。以下的代码解说了如何为一个整数分配内存空间:
int*pNumber;
pNumber= new int;
第一行代码声明了一个指针pNumber,第二行代码分配了一个整数的空间,并使pNumber指向这一段新分配的内存。见下面完整例子
#include
int*pPointer;
void SomeFunction()
{
pPointer= new int;
*pPointer= 25;
}
void main()
{
SomeFunction();//让pPointer指向某些东西
printf("Value of*pPointer:%d\n",*pPointer);
delete pPointer;
}
最后一行的delete pPointer用于释放已分配的内存,你不将内存delete掉,你的程序就会得到一个“内存泄漏”。如果出现了内存泄漏,那么除非你关闭应用程序,否则你将无法重新使用这段泄漏的内存。但是尝试delete一段已经释放的内存是十分危险的,这可能会导致你的程序崩溃。
向函数传递指针
向函数传递指针的技术非常有用,见下面一段程序:
#include
void AddFive1(int Number) //得到Number的一个拷贝
{
Number= Number+ 5;
}
void AddFive2(int* Number) //得到Number的指针
{
*Number=*Number+ 5; //操作Number数据本身
}
void main()
{
int nMyNumber= 18;
printf("My original number is%d\n", nMyNumber); //=18
AddFive1(&nMyNumber);
printf("My new number is%d\n", nMyNumber); //=18
AddFive2(&nMyNumber);
printf("My new number is%d\n", nMyNumber); //=23
}
AddFive2函数中Number之前的“*”是告知编译器我们要在指针Number指向的数字上加5,而不是向指针本身加5。
我们亦可以在函数中返回指针,像下面这个样子:
int* MyFunction();
在这个例子中,MyFunction返回了一个指向整数的指针。
指向类的指针
定义一个类:
class MyClass
{
public:
int m_Number;
char m_Character;
};
然后定义一个MyClass的变量:
MyClass thing;
也可以这样定义一个指向MyClass的指针:
MyClass*thing;
然后,你可以为这个指针分配一些内存:
thing= new MyClass;
因为thing并非一个MyClass,而是一个指向MyClass的指针,因此,我们必须使用一种不同的转换方式。将“.”(点)替换为一个“->”。请看下面这个例子:
class MyClass
{
public:
int m_Number;
char m_Character;
};
void main()
{
MyClass*pPointer;
pPointer= new MyClass;
pPointer->m_Number= 10;
pPointer->m_Character='s';
delete pPointer;
}
指向数组的指针
你也可以使指针指向数组,如下:
int*pArray;
pArray= new int[6];
这将创建一个指针pArray,它会指向一个6个元素的数组。另一种不使用动态分配的方法如下:
int*pArray;
int MyArray[6];
pArray=&MyArray[0];
见下例:
#include
void main()
{
int Array[3];
Array[0]= 10;
Array[1]= 20;
Array[2]= 30;
int*pArray;
pArray=&Array[0];
printf("pArray points to the value%d\n",*pArray); //=10
pArray++;
printf("pArray points to the value%d\n",*pArray); //=20
pArray++;
printf("pArray points to the value%d\n",*pArray); //=30
}
要想使指针移到数组的下一个值,我们可以使用pArray++。也可以pArray+ 2使这个数组指针移动两个元素。要注意的一点是,你必须清楚数组的上界是多少(在本例中是3),因为在你使用指针的时候,编译器不能检查出来你是否已经移出了数组的末尾。所以,你可能很容易地使系统崩溃。
数组的指针(例如int* pNumberSet),也可以看作一个数组。比如pNumberSet[0]相当于*pNumberSet,pNumberSet[1]相当于*(pNumberSet+ 1)。
如果用new为一个数组分配空间的话,就像下面这个样子:
int*pArray;
pArray= new int[6];
delete[] pArray;// 那么必须这样释放它:
delete之后的[]。这告知编译器它正在删除一个整个的数组,而不是单独的一个项目。你必须在使用数组的时候使用这种方法,否则可能会获得一个内存泄漏。
引用
从某种角度上来说,引用不属于指针。引用和指针十分相似,在很多情况下用哪一个都可以。“&”读作“the address of(……的地址)”但在声明的时候例外。在声明的这种情况下,它应该读作“a reference to(……的引用)”,如下:
int& Number= myOtherNumber;
Number= 25;
引用就像是myOtherNumber的指针一样,只不过它是自动解析地址的,所以它的行为就像是指针指向的实际值一样。与其等价的指针代码如下:
int* pNumber=&myOtherNumber;
*pNumber= 25;
指针和引用的另一个不同就是你不能更换引用的内容,也就是说你在声明之后就不能更换引用指向的内容了。例如,下面的代码会输出20:
int myFirstNumber= 25;
int mySecondNumber= 20;
int&myReference= myFirstNumber;
myReference= mySecondNumber;
printf("%d", myFristNumber);
当在类中的时候,引用的值必须由构造函数设置,像下面这种方法一样:
CMyClass::CMyClass(int&variable): m_MyReferenceInCMyClass(variable)
{
//这里是构造代码
}
引自http://mba.ce.cn/kao/ksit/itxxzn/200608/11/t20060811_8100388.shtml
评论