一、const
const的应用是一个老生常谈的技术点。前面反复的分析很多次,包括最新的const的扩展等等。但const应用几乎是贯穿着所有开发的应用的。可以这样说,只要稍微大一些的程序,都会用到const关键字,即使开发者自己不使用,调用的库或第三方的接口中大概率也会存在。
const不仅仅是一种常量的限定关键字,更是作为一种代码级别的安全机制为各类开发人员所重视。
二、c和c++中const的应用
在c/c++中,const的应用非常广泛。从函数、对象、函数参数到变量等都可以看到const关键字的影子。如果开发者只是在c/c++中任何单一一个环境中使用const,其出现问题的可能性都不大。但问题往往是由于c++对c的兼容性,导致很多开发者稀里糊涂的就把c/c++混合编程了。
这种应用,到最后就出现一个问题,如果C++的代码恰好也符合C的规范,那么用C编译器编译可能就没有问题;但如果用C++的编译器来编译就有可能出现问题。
这对于老油条们来说,可能很快就定位出来了问题的原因。但对于一些新手或不太熟悉此方面的技术点的开发者来说,可能就得大费一番周章,甚至觉得不可思议,遇到了玄学问题。
三、二者的区别
对于c/c++中const应用的主要不同,可以从以下几点来分析:
- 功能范围不同
这个属于C和C++语言的范畴,比如支持类内成员函数的const,类内无法static与const共同使用等等,这个不是重点 - 初始化不同
C语言允许对常量不进行初始化,但C++则要求必须进行初始化(类成员允许使用列表初始化) - 常量表达式的限定不同
C语言中const只代表只读,不是真正的常量(这意味着可以利用一些技巧绕过只读限制);而C++中则是真正的常量。所以前者不能作为数组之类的大小限定或switch中的case标签使用,但C++则可以 - 链接属性不同
如果说前面的两个点,即使出现问题也很容易解决的话,这点就是挖坑的典型代表了。在C语言中全局const默认的链接属性是外部链接,可以为其它编译单元访问;而C++中则为内部链接,仅在当前文件可见。那么想要让外部的其它编译单元看到,则必须显式的使用extern来标记相关常量
当然在其它的一些细节上,比如对指针的限定(C++限定更严格)以及对返回值的限定上(C++有一些特有的功能如常函数等),也存在着一些微小的不同。但整体上来看,几乎可以认为是一致的。这里就不再展开分析,有兴趣可以查找一下相关的资料,认真分析一下。
四、例程
下面看一个例程,如果能明白这个例程的意义,就可以明白上面对c/c++中const的区别中的第四点,有一个清醒的认识:
//main.cpp#include<stdio.h>// 其它编译单元const变量externconstintkInit;intmain(){printf("reference kInit %d\n",kInit);return0;}//extern_demo.cpp// 定义const变量/*extern*/constintkInit=100;大家可以分别使用C或C++的编译器自己去试一下(大家可以看看用gcc编译如果不修改文件后缀名会怎么样?),看看有什么区别,编译错误会不会消失?或者打对extern的注释,同样也是没有问题的。那么如何才能查看这个属性呢?其实有很多的工具可以利用比如使用nm命令(前面对其有过详细分析说明):
# 1. C编译 gcc -o main main.c extern_demo.c nm main|grep kInit 0000000000002018 R kInit # 2. C++编译extern解注释 g++ -o m main.cpp extern_demo.cpp nm m |grep kInit 0000000000002018 R kInit # 3. C++编译extern注释 编译无法通过,报<main.cpp.o: in function `main': undefined reference to `kInit' # 4. C++直接编译extern_demo.cpp为中间文件 g++ -c extern_demo.cpp nm extern_demo.o|grep kInit 0000000000000000 r _ZL5kInit有没有发现,如果在C++的编译中,不使用extern关键字,变量kInit前面是一个小写r,而在C语言及增加extern关键字后,其前面为大家的R。大写代表是外部链接属性,意味着外部编译单元可以访问;而小写则代码内部编译链接属性,只能在内部编译单元访问。
五、总结
其实很多编程的细节,特别是C和C++混合编程中的细节,往往不经过实践很难有深刻的印象。但是这种细节的遇到又经常是一个小概率的事件。这两者结合在一起,就会让很多的开发者,特别是c/c++混合编程的人员有一种玄幻的感觉。其实不是玄幻,是技术没掌握到位。