C++面试题——const 和 static
虽说不太喜欢这种问语言特性的题目,但是国内好多公司貌似就喜欢问这个,还觉得问这个很高端,就把他们常问的一些东西写下来做个总结,有的东西还是有些意思的,有些东西其实都没个固定的答案。不出意外将会写一个系列包括:
- const和static的区别
- iterator和引用的实现以及与指针的区别
- 从dynamic_cast说C++的虚机制和对象内存布局
当然也保不齐出意外就不写了。这里面不会讨论具体的C++语法问题,更多的是设计实现机制的东西,其实这些实现机制不是标准里要求的,每种编译器的实现机制可能都不一样,有的书像《深度探索C++对象模型》是这方面比较有名的一本书,但是由于年代比较久远了,在我的实验中这本书的很多细节已经和当今的编译器不一样了。而许多介绍这方面东西的博客也不见得和最新的编译器实现一样所以如果有兴趣的话还是自己动手探索一下,不要过于相信书和别人写的,本来这些东西就没有标准答案。
先从个简单的问题开始,const和static的区别。这其实是个很不好的题目,从语言的层面上讲,这两个东西不是个横向可比的东西,他们的功能集合几乎是正交的,不像所谓的引用和指针,迭代器和指针那样有相关性,但是就是有面试官喜欢问。
由于这个问题实在不回答,就把static和const分别是怎么做到的说一说。
static的特性主要有两个,连接期被分配到了data段,即使是在函数调用中定义也不会在栈中产生,而是在程序加载期就被加入了内存。第二点就是编译生成的目标文件中不会将static变量加入到export表中,也就是说其他模块是不会访问到这个static变量的。
具体来可以写一个实验程序,定义几个全局的普通变量和全局的静态变量,再在main函数里定义几个普通变量和静态变量,打开调试模式观察这些变量的地址,我是用VS2010调试的,不同编译器结果可能会有差别。可以发现全局的静态变量,局部的静态变量和全局普通变量的地址是相互靠近的,main函数中的普通变量是在相隔较远的另一个位置。由此可证明static变量是在和全局变量相互靠近的区域,也就是程序的data端,而不是在栈空间内,这样就保证这个变量不会随着函数调用和返回的入栈出栈把static变量抹掉。
static第二个特点有点像private关键字,规定这个变量只能在本文件中使用而不会被其他文件使用,即便你在别的文件中加入extern关键字也找不到这个变量。以为extern的实现机制是在链接时期通过程序依赖的目标文件的符号导出表寻找相应的符号,static变量不会加入符号表,别的文件也就看不到这个符号。
const表面含义貌似是个常量,但实际上还是占据一个内存位置的变量,但是它的值一般实在编译时期就决定了,所以很多情况下就被编译优化用一个常量代替了,根本没有这个变量的踪影。除非有这个变量的引用或者指针暗示这个所谓的常量可能会被修改才会占用一个内存空间。
换句话说就是C++所谓的const只是在语言层面上提供一个无法修改的保障,这个保障就是说你直接修改这个变量编译无法通过。而不是通过把这个变量放入只读区域或者把存有这个变量的内存标成只读来实现的。所以要突破这层保护是很容易的,包括C++自己也提供了const_cast,我们自己也可以通过指针来修改这个所谓const变量的值。
int main()
{
volatile const int a = 10;
int *c =(int*) &a;
*c = 5;
cout<<a<<endl;
return 0;
}
可以通过这个简单的程序自己测试一下。