理解右值语义
个人对右值语义的理解
执行一段非法C++代码时出现了问题
1 |
|
输出为:
1 | Before: |
地址&a
和p
是相等的,然而a
和*p
的值却不相同。原因在于C++编译器在编译时会采用一种叫做变量折叠的技术。
变量折叠:在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。
将上述代码转换为C语言之后,地址相同值不同的问题没有发生.
查询到这是种编译器优化之后,开启-O0
依旧无法避免.
最后发现是因为C和C++的const实际执行的语义不同而引起的.
C语言中,const修饰变量将被放在.rodata段中,不代表是个常量,单纯意味着只读,是一种运行时const.
C++语言中,const修饰变量将在编译时直接将变量引用位置替换成对应常量,相当于具有类型保护的define,是一种编译期const.
在C和C++中,const变量确实会被上述代码所改变,但是C++在运行时改变const,再次读取的还是编译器符号表中的常量数据.
解决方法是在变量前加上volatile,volatile告诉编译器每次调用变量都需要从内存重新取值,从而解决问题.