让代码做证----关于 const与*的组合

类别:编程语言 点击:0 评论:0 推荐:

前几天我们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 的意义! 大家不妨试一试!

本文地址:http://com.8s8s.com/it/it22498.htm