afxid的专栏

路漫漫其修远兮 吾将上下而求索

用户操作
[即时聊天] [发私信] [加为好友]
afxidafxidID:afxid
118992次访问,排名755,好友0人,关注者1人。
afxid的文章
原创 26 篇
翻译 1 篇
转载 85 篇
评论 27 篇
afxid的公告
把CSDN的BLOG作为存放自己学习时心得、笔记、引用的地方吧 当然也希望大家能从这里得到一些帮助 ^_^
最近评论
jichre:学无止境!
路漫漫其修远兮,吾将上下而求索!
lover_maxue:初学perl这些还好基本能明白了,谢谢!
huglwid:你的文件坏了!怎么配置,能不能也给我发个邮件?
8612557@163.com
tobel:你的文件坏了!怎么配置,能不能给我发个邮件?bs_yjg@126.com
ollydbg23:你这个文章写的很好,谢谢
但是我看起来还是云里雾里,呵呵,我水平太差了。。。
文章分类
收藏
    相册
    友情链接
    CSDN
    Joy Sun's Blog
    华中大在线
    零蛋鱼的space
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 浅析带const的指针或引用复杂声明收藏

    新一篇: The String Formatters of Manor Farm(zz) | 旧一篇: 深入探讨C++中的引用(zz)

    C++中的const与non-const、指针和引用本来就搞得人头晕了,再把复杂的声明结合在一起,比如看下面这个
     const double * const &  crcdval = &cdval;
    你看的明白吗?呵呵,如果不是很明白,那就读一读我的这篇心得吧。

    ●复杂的ptr和const声明

    #include <iostream>
    #include <vector>
    using namespace std;

    struct X
    {
       X(int i) : m_i(i) { }
       int m_i;
    };
    void main()
    {

       // 我把每个变量的类型都写出来了
       // correct
       const X cx(10);
       const X * pcx = &cx;
       //typeof(pcx) = const X (*)
       const X * const cpcx = &cx;
       //typeof(cpcx) = const X (*const)

       cout << sizeof(const X *const(*const(*const))) << endl;

       const X * const * ppcx = &pcx;
       //typeof(ppcx) = const X (*const(*))
       const X * const * const cppcx = &cpcx;
       //typeof(cppcx) = const X (*const(*const))

       const X * const * const * const cpcpcpx = &cppcx;
       //typeof(cppcx) = const X (*const(*const(*const)))

       cout << &(vector<int>()) << endl;
       cout << sizeof(int(& (*)(int[20],int&,double**))[100]) << endl;
    }

     今天才发现原来以前C++老师讲const时讲错了,const int * p 和 int const * p是等价的,p为pci: Pointer to a const int(const int *);而int * const p中p为cpi:const pointer to int(int *const),我也一直都记错了。

     另外,比如
     const X * const * const cppcx = &cpcx;
        //typeof(cppcx) = const X (*const(*const))

        里面的第2个const可能会让很多人迷惑。我的理解是:它既修饰前面的指向const X的指针本身,看成是"const T *const"的后面那个const;又修饰了后面的那个指针*,说明它指向的对象是const的,看成是"T const *"的形式,其中的T展开就是const X*.

     

        利用编译原理中的词法生成规则来描述它,我们可以清楚地看到这个声明语句是怎么得来的。
        首先定义生成规则:

        产生式:{
      指针的声明语句→T id [= exp];
      T→(const T)|(T const) * [const]
             }
       
        上面的那个复杂的声明语句的推导过程:

      指针的声明语句 => T id = exp; 
       => T const * const id = exp;
       => const X * const * const id = exp;
       => const X * const * const cppcx = &cpcx;
        这里的两个理解其实是等价的,因为这是一个多重指针,第2个指针指向的就是第一个指针里面的地址值。
    所以第一个指针本身是const和指向这第一个指针的第二个指针所指向的对象为const当然是一样的了。
        以前我老是觉得,C++中为什么不规定只使用单一形式的const,而要这样搞的两个形式等价,现在看来其实应该是const T *用的人很多,而T const * 又是语法所必须的,所以就无从取舍。当然可以只保留T const *的形式:)。&的写法与此类似,只是只有const T&和T const&,而由于referrence本身的要求,就是一个const的了,所以没有T & const的写法.       

    ●为什么这个const不能少

    今天偶尔看到《c++ Primer》中讲referrence的那一章中有个例子,

    const double cdval = 3.14;
     const double * pcd = &cdval;
     const double * const &  crcdval = &cdval;

     double dval = 6.28;
     double * const & rd = &dval;

     书上说到其中的第3行,很可能大部分人都不能把它直接写对,因为里面的两个const一个都不能少!
    需要前面的那个const是显然的,如果去掉cl会提示
    error: a value of type "const double *" cannot be used to initialize an entity of type "double *const &"
    即从const type到non-const type的转化是不允许的。

    而如果去掉第二个const会怎么样呢?(可以只通过最后2行的例子来说明这个问题)
    error: initial value of reference to non-const must be an lvalue
     我觉得,第2个const可以理解做同时修饰(*const)和(const&),这就点和复杂的ptr和const声明一样,稍后会解释。这里因为&dval是non-lvalue表达式,而没有const修饰&,则它必须用一个lvalue表达式来初始化,故错误;而根据修饰转换的原则,non-const type 到const type的转化是允许的.就是"const double *"可以转化为"const double *const &" 所以只有两个const都加上才能通过编译。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         

    发表于 @ 2006年03月23日 21:11:00|评论(loading...)|编辑

    新一篇: The String Formatters of Manor Farm(zz) | 旧一篇: 深入探讨C++中的引用(zz)

    评论

    #ollydbg23 发表于2008-01-11 09:50:27  IP: 60.12.143.*
    你这个文章写的很好,谢谢
    但是我看起来还是云里雾里,呵呵,我水平太差了。。。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © afxid