http://blog.csdn.net/beyond0525/article/details/7409305
下面通过一个例子来解析 常量指针 和 指针常量,我们先总结一下 常量指针 和 指针常量 的区别
首先一定要明白哪种定义方式是常量指针,哪种是指针常量,这里可以记住三句话加深记忆:
* (指针)和 const(常量) 谁在前先读谁 ;*象征着地址,const象征着内容;谁在前面谁就不允许改变。
指针常量因为指向是固定的,所以定义时必须初始化,明确其归宿。
--------------------------------------------------------------------------------------
迷途指针: 当对一个指针执行delete后(编译器对这段内存标记,告诉系统这段内存可以进行再分配)该指针就是迷途指针。
禁止使用迷途指针和空指针;
禁止对同一块内存重复删除,空指针重复删除没有什么影响。
const 常量定义时,必须同时初始化,且以后不能再改变,原因是不能对常量赋值。如 const int a =5; (a=3; 错误)
char* p="0123",赋值号右边的类型为const char* ,sizeof(p)=4,strlen(p)=4。
char p[]="0123",sizeof(p)=5,strlen(p)=4,原因是内存中存储时末尾系统自动加'\0'字符。
sizeof()是运算符,来测类型,变量,数组啊占用的内存大小,但是不能测动态数组。
strlen()是字符串处理函数(#include<cstring>,C中对应#include<string.h>),来测char*或者char[]实际长度,不包括'\0'。
如果在某个函数里定义 char p[]="0123",return(p)。p是一个局部数组,函数调用结束后,局部变量p被释放。如果再在调用的函数里使用p时,很危险,往往会出错(类似于使用迷途指针)。因为p开始的地址可能已经被编译系统收回,分配给其它变量(int,double...)。
如果在某个函数里有 p="0123",return(p),如果p是全局变量,函数调用结束后,p不被释放直到主函数结束。
string 是C++中一个类(#include<string>),有相应的成员函数来测它的实际字节长度string::size()或者string::length();string::capacity()是系统当前自动分配给string对象的内存大小,而且是随着str变化会自动调整,str.capacity()>=str.length()。
除此之外string类还有其他的成员函数: 比如 获取元素的str[i],str.at(i); 操作符“+=“ ; str.append(*).....等等成员函数。
类中的const成员函数,在.h头文件和.cpp函数实现时,都必须冠以关键字const。
const成员函数只能用类中的变量,不能修改它们,所以const成员函数不能调用能改变变量的非const成员函数。如果非要改变变量值,就要将变量冠以mutable关键字。
数组作为参数传递给函数时,传的是指针,是数组首元素的地址。编译器不知道数组的大小,要想在函数里知道数组的大小,长度必须由另一个参数传进来。
-------------------------------------------------------------------------------------
好吧,让我们来看这个例子:
- int a =3;
- int b = 1;
- int c = 2;
- int const *p1 = &b;//const 在前,定义为常量指针
- int *const p2 = &c;//*在前,定义为指针常量
常量指针p1:指向的地址可以变,但内容不可以重新赋值,内容的改变只能通过修改地址指向后变换。
p1 = &a是正确的,但 *p1 = a是错误的。
指针常量p2:指向的地址不可以重新赋值,但内容可以改变,必须初始化,地址跟随一生。
p2= &a是错误的,而*p2 = a 是正确的。
下面是在Vim编辑器中的调试结果
上述代码在注释 18行 和 24行 代码后才能正确输出,下图是正确结果
输出结果可以看出,对于常量指针p1,改变其地址指向,内容也随着地址的改变而变化了。
而对于指针常量p2,初始化后地址就固定了,内容可以随时重新赋值。
对于常量指针p1,我们可以改变它指向的地址,但不能改变指向的内容,如果改变了,就会出错,下面是18行代码取消注释后编译器提示的错误:
对于指针变量p2,我们可以改变他指向的内容,却不能改变它指向的地址,如果改变了,就会出错,下面是24行代码取消注释后编译器提示的错误: