理解const的内存分配
1. 基础知识
在C语言例,const的含义是被称为一个不能被改变的普通变量,而在C++中其含义就不尽相同。尤其,目前许多的资料都指出:C++中的const常量,C++编译器都会尽量避免const 常量的内存分配,只有当不得已的时候才会分配具体的内存空间给const变量。
具体什么情况下会分配内存给const变量,目前已经确定的有如下几种情况:
2. 解析const int作为全局变量时的内存分配
只看干巴巴的文字,总有一股难以理解的感觉。为此,决定实际检验下。
有如下代码,通过反汇编以及查看符号表的方式来确定globa_const_int_N的内存分配,同时以global_const_int_N来做对比。
#include <stdio.h>
int global_int_M = 6;
const int global_const_int_N = 7;
int main(int argc, char const *argv[])
int j = global_int_M;
printf("%d\n",j);
j = global_const_int_N;
printf("%d\n",j);
return 0;
}
源代码编译:
g++ -g testConst.cpp -o testConst
objdump进行返汇编,并查看符号表
objdump -tS testflush > symc.txt
重点来了,查看符号表,看具体globa_const_int_N和global_int_M的存储位置。
这里我们可以很清楚的看到globa_const_int_N和global_int_M是分别存放在.rodata和.data字段的,并且两者的存储空间大小均为4(第四列的0000000000000004代表分配内存大小为4)。
相对应的第一列的0000000000000004和0000000000000004分别代表着对应的内存地址,有兴趣的同学可以打印一下试试。
那么我们再来看一下反汇编得到的main代码:
图中214,215,216行是从global_int_M的存储空间内取出数据然后存储到对应j的存储空间中。
图中223和224行则是将global_const_int_N常量对应的值直接存储到j中!
可以发现,编译器是直接从常量表中取出对应的值存储到j,而不是像global_int_M一样从内存空间中取值。
在这里,我又继续考虑编译器优化会造成的影响。因而在此实验如下:
选择高级的优化等级:
可以看到符号表中已经不存在global_const_int_N。说明其已经不再占有内存了。
查看反汇编代码 :
经过优化过后的汇编代码的易读性已经不如最初。但仍可发现:132行是从global_int_M的存储空间内取出数据然后存储到对应j的存储空间中。,对于137行则是编译器直接将常量值替7存储到j中。
从上我们直到如果对一个全局const int赋值常量的时候,它根据编译器的优化会选择存放在:
- 常量表中
- 或者编译器直接使用其常量,而不进行存储。
const全局变量内存分配的其他信息
但是const变量的知识显然远远不止这些:
“`cpp
#include
3. 小结
- 对于const全局常量,如果初始值是字面值常量,一般会存放在常量表中,编译器在编译过程中就会直接使用常量表中的值来进行语句的操作。如果经过优化,可能会使得直接使用常而放弃存储在常量表中。
- 对于编译器没有办法处理的初始值常量,一般就需要分配到内存空间,然后等待运行时进行赋值,取值时候也是从内存空间中提取。
- 对于非static 的 const局部变量(如函数中),由于其是局部变量,符号表中将不存在其值,如果需要内存空间也是在栈中进行分配。根据编译器的优化,以及const 变量初始值的不同来决定是否需要分配内存空间。
- 对于static 的 const局部变量(如函数中),会根据编译器的优化能力,以及初始值,来决定其是不进行存储,还是直接存储在常量符号表,或者是栈中等等均有可能。
- 对于第三点和第四点可以字迹尝试验证。
4. 后记
对于C++这门语言,每次一个很小的知识都能牵扯出来一大堆东西,这也是让人又爱又恨的。本来我想写的是const变量的内存分配,虽然来说,目前仍没有跑题,但是还是不是很完善,除此之外,对于类中const 变量的使用和其内存分配也是非常只得关注的。这些东西留到下次再写吧。