前几天我们QQ群提出了这么一个问题: 请问: int **const a; int *const * a; int const** a; 他们的区别? 我下线后就写了一些测试程序来作为我对这个问题的理解: 程序1:关于**const============================ #include <iostream> #include <conio> using namespace std; //------------------------------ int main(int argc, char* argv[]) { int a=123; int b=456; int c=789; int *pa=&a; int *pb=&b; int *pc=&c; int **const ppa=&pa; //ppa 是常量 ,ppa必须先初始化,否则会有错误编译错误发生 cout<<**ppa<<endl; getch(); /* ppa=&pb; //无法修改ppa的值,进一步说明ppa是常量 cout<<**ppa; getch(); */ *ppa=&c; //*ppa是可以修改的 cout<<**ppa<<endl; getch(); **ppa=777; //**ppa是变量修改了**ppa就是修改了c的值 cout<<"**ppa="<<**ppa<<endl; cout<<"c ="<<c <<endl; getch(); } 程序2:关于*const*============================ #include <iostream> #include <conio> using namespace std;
int main(int argc, char* argv[]) { int a=123; int b=456; int c=789; int *pa=&a; int *pb=&b; int *pc=&c; int **ppt=&pc; int *const* ppa=&pa; //ppa初始化与否都无所谓,说明ppa是变量 cout<<"(long)( ppa)"<<(long)( ppa)<<endl; cout<<"(long)( *ppa)"<<(long)( *ppa)<<endl; cout<<"(long)(**ppa)"<<(long)(**ppa)<<endl; //如果ppa不初始化,这个语句会产 //生异常(至少在我的机子上是这样) cout<<"(long)( &pa)"<<(long)( &pa)<<endl; cout<<"(long)( pa)"<<(long)( pa)<<endl; getch(); ppa=&pc; /* //注意:下面说的使用是指修改其值,而不仅是读取其值 *ppa=pc;//无论ppa是否初始化这一句总是产生编译错误=>编译器提示:无法修改一个const对象 //由此可见*ppa是一个常量,我们无法修改*ppa的值,而无论ppa是否初始化都一样。 //如果ppa不初始化,那么ppa和*ppa都指向一个随机地址,由于*ppa的值无法改变,所以 //这时使用ppa和*ppa是安全的(这一点很有意思,或许我们可以利用这一点作点什么)但 //是,如果使用**ppa就是错误的; */ **ppa=777; //这一句能够顺利执行,说明**ppa是可以被修改的 cout<<"**ppa="<<**ppa<<endl; cout<<"a ="<<a <<endl;//修改了**ppa就是修改了a的值 getch(); return 0; }
程序3:关于*const*============================ #include <iostream> #include <conio> using namespace std;
#pragma argsused int main(int argc, char* argv[]) { int a=123; int b=456; int c=789; int *pa=&a; int *pb=&b; int *pc=&c; int **ppc=&pc; int const d=888; int const*pd=&d; int const**ppd=&pd; int const e=888; int const*pe=&e; int const**ppe=&pe; int const** ppa=ppd;/* 这个更有意思:ppa不能在定义时用&pa或ppc初始化,一旦写 了初始化代码就会有下面的编译错误发生 Cannot convert 'int * *' to 'const int * *' 但是可以用ppd初始化 */ /* ppa=&pa;//即使在定义后初始化也是上面一样的错误 */ ppa=ppe;//这一句是可以的表明ppa并不具有常量的性质ppa是可以改变的 //但是只能指向与自己同类型的两量 /* *ppa=pc; //这一句会有"程序访问非法地址"的错 //误所以这样用是错的。但是,不是编 //译期错误,这就说明*ppa是可以更改的量(虽然是不合法的) //而不是属于 const 的。//这里的分析好象有问题大家还是讨论讨论 */ *ppa=pe; //但是,这一句倒是可行的 // ppc=ppe; //这两句仍然有前面一样的编译错误:说明ppc是常量性质的无法更改其值 /* **ppa=777;//这一句会有无法修改const对象的错误 //这说明**ppa是常量性质的 */ getch(); return 0; }
总结:============================ 由const修饰的量是常量性质的!该量的值不可更改. **const *const* const**
例如: const* p ==> *p 不能更改,但是 p 自己的值是可以改变的 const** p==> **p 不能更改,但是 *p 和 p 的值是可以改变的 *const* p==> *p 不能更改,但是 p 和 **p的值是可以改变的 **const p==> p 不能更改,但是 *p 和 **p的值是可以改变的 这个const好象在我们“向改写的对象赋值过程中,进行寻址时” 加了一把锁或一堵墙:他修饰谁,谁就不能被赋值寻址时被 找到(编译期错误,当然读取都是允许的)。
通过这我们可以了解到: const int& AA::func(const int&x )const; │ │ └修饰整个成员函数:不该变类的内部数据 │ └修饰参数:该函数不改变外部参数x的值 ├修饰返回值:调用该函数的代码不能改变返回的引用值(否则 └ 我们才可以这样用fun(a)=12// 事实上我们每个人都这样用过:cout<<...<<...)
通过这些也可以推导出:Type const*const*const a 的意义! 大家不妨试一试! 
|