正好跟同学讨论到如何理解指针常量与常量指针。 就顺着这个思陆陆续续把指针及const的相关内容做个整理吧,也算是自己一个巩固与理解的过程。
1.指针常量与常量指针
(1)指针常量
强调是指针, 这个指针是一个常量
那它的定义应该是 type * const p ,在这里const修饰指针。
它的意思是指针本身不可变,那就是这个指针指向的地址不可再变。
既然它指向的地址不可变,那就要注意定义时一定要初始化。
即:
int* const p = &m; //我习惯int* 放一块把它们理解成一个指针类型
p指向了变量m的内存地址,可以通过*p来存取m。 这里p指向的地址不可变,但它所指向内存的内容是可变的。
所以
*p = 100 ; //correct
p =&n; //err
(2)常量指针
强调是指针,指针指向的是常量(值不可变)
那就是const修饰一个常量(*p,对指针取地址是该变量本身的值)
type const * p
*p整体不可变,但是p的指向是可变的。 所以不必非定义时初始化。
int a =10,b=20;
int const * p = &a;
p=&b; //correct
*p = 30; //err
(3)指针常量+常量指针
int const *const p = &a;
这句话的意思是指针指向和指针指向的内存值均不可修改。
(4)const可以接受const和非const,但非const只能接受非const。
(这个在const修饰函数参数时尤要注意)
非const指针不能保证接收const值后不做修改,所以语法不允许它。
int a=10;
const b=10;
int const *p =&a;//correct
p=&b; //correct
int *pt = &b; // err
int *pt = &a; //correct
- 指针数组和数组指针
(1)指针数组表明数组元素是指针
int* at[10]={&a,&b,&c}; //还是把int*理解为一个整体,指针类型
(2)数组指针是指向数组的指针
int (*parray)[10] ={0};
//int a[10] = 0; parray=&a; (*parray = a)
(*parray)[0] = 1;
(3)typedef定义
//定义一个数据类型
typedef int (myTypeArray)[10];
myTypeArray myArray;
//定义一个数组指针类型
int a[10];
typedef int (*PYTypeArray)[10];
PTyepArray myParray;
myParray =&a;
(*myParray)[0]=10;
//定义一个指向数组类型的指针
int (*MyPointer)[10]={0};
(*MyPointer)[0]=10;
3.函数指针
//定义一个函数类型
add(1,2);
typedef int (MyFuncType) (int a,int b);
MyFuncType *MyPointerfunc=NULL:
MyPointerfunc =&add;
or: MyPointerfunc =add;
//定义一个函数指针类型
typedef int (*MyFuncType) (int a,int b);
MyFuncType MyPointerfunc:
MyPointerfunc =add;
//定义一个函数指针(指向一个函数的入口地址【函数名】)
int (*pointer)(int a,int b);
pointer = add;
定义指向类成员或类成员函数的指针
<数据类型><类名>::<指针名>[=&<类名>::<非静态数据成员>]
string Student::*ps = &Student::name;
cout<<s.*ps<<endl;
cout<<s2.*ps<<endl;
Student *pp = new Student("wangwu",1003);
cout<<pp->*ps<<endl;
<数据类型>(<类名>::<指针名>)(<参数列表>)[=&<类名>::<非静态成员函数>]
void (Student::*pf)() = & Student::dis;
(s.*pf)();
(s2.*pf)();
(ps->*pf)()
4.const 引用
const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化
int &ref=val; err 非 const 的引用不能使用相关类型初始化
实际上,const 引用使用相关类型对象初始化时发生了如下过程:
int temp = val;
const int &ref = temp;
如果 ref 不是 const 的,那么改变 ref 值,修改的是 temp,而不是 val。期望对 ref 的赋值会修改 val 的程序员会发现 val 实际并未修改