美文网首页程序员iOS Developer代码改变世界
朝花夕拾:const关键字的要点和实现机制

朝花夕拾:const关键字的要点和实现机制

作者: Maru | 来源:发表于2016-11-23 21:27 被阅读296次
    C Programming Language.png

    0x00 最初的起点

    首先是一道烂大街的题目:以下四个变量有什么区别?

    Problem.png

    答案很简单:

    1. v1是一个指针常量,即指针所指向的值不可改变,但是指针所指向的地址可以改变。
    2. v2和v1相同。
    3. v3是一个常量指针,即指针所指向的内存地址不可改变。
    4. v4是一个指向常量的常量指针,即无论是指向的内存地址,还是内存地址中的值都是不可改变的。

    可以看到,这个基本上就是依靠记忆的东西,并没有什么理解上的难点,只是记住之后没过一段时间可能就又混淆了。

    记忆方案一

    1.如果const位于的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
    2.如果const位于
    的右侧,则const就是修饰指针本身,即指针本身是常量。

    恩... 似乎很有规律的样子,但是我记性很差,这种规则对我来说还是太绕,过一段时间就不确定会不会记反了。

    记忆方案二

    Bjarne在他的The C++ Programming Language里面给出过一个助记的方法:

    把一个声明从右向左读。

    char * const cp; ( * 读成 pointer to )
    cp is a const pointer to char

    const char * p;
    p is a pointer to const char;

    恩。这样确实大大的降低了记混的情况了,但是虽然这种方法已经很简单了,但是对于英语不是母语的人来说,还是需要绕一层的,那么有什么更加简单的记忆方法吗?

    记忆方案三

    const修饰前面的关键字,只有当const开头时才修饰后面的关键字

    即:当const前面是char int之类的类型关键字时,表示修饰的是指针所指向的内容;而当前面的是指针运算符(*)的时候,那么表示修饰的是该指针;当const位于表达式首位时,请参考第一条。

    0X01实现机制

    其实const关键字并没有多么复杂的实现方法,只是在编译器的层面做了modify的限制,而const变量和非const变量在runtime期间其实并无卵分别,最好的证据就是编译过程中的汇编代码了,证据如下:

    首先我们有两段简单到妈都不认得的C++代码:

    代码一

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int a = 100;
        return 0;
    }
    
    

    代码二

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
        const int a = 100;
        return 0;
    }
    
    
    

    这两段代码唯一的区别就是,一个int变量有const修饰,而另一个int变量没有const修饰。OK,接下来我们编译成汇编,使用下面的命令:

    g++ -S demo.cpp

    编译之后得到的汇编代码对比图如下所示:

    汇编代码对比.png

    我们可看到,两者并无什么不同,也就是说,汇编并不会对const的变量做什么特殊的处理,const只是在编译的层面给程序做了限制。

    但是,这里又有一个问题,当我们把代码修改成下面那样的时候:

    代码一

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int a = 100;
        cout << a << endl;
        return 0;
    }
    
    

    代码二

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
        const int a = 100;
        cout << a << endl;
        return 0;
    }
    
    
    

    这里的代码与上面的代码的区别无非是,访问了a的值,按照上面的理论,编译后的代码应该没有不同,但是世事难料,对比图如下:

    g++编译下对比.png

    我们可以看到竟然还是存在差别的,但是根据查阅资料和个人猜测,我认为可能的原因是:const的变量存储的时候确实没有特殊处理,但是在取值时,并不会访问const变量的内存地址,而是通过一个全局符号表(symbol table)替换了该值,所以才会出现这样的汇编代码的差别。

    0X02 最后说的话

    说到底还是不懂汇编,有空也可以研究一下,如果有汇编大神路过,也请不吝赐教!

    相关文章

      网友评论

        本文标题:朝花夕拾:const关键字的要点和实现机制

        本文链接:https://www.haomeiwen.com/subject/yrulpttx.html