C++ 各种全局常量的声明方式的优缺点

本文探讨了C++中全局常量的声明方式及其优缺点。const变量不应在头文件中声明,应在cpp文件中定义,以避免性能下降。编译器对const进行了优化,使其在某些情况下等同于#define常量,但提供了类型检查和命名空间。const在函数重载和编译效率方面优于#define。同时,enum作为const变量的一种形式,节省内存但类型限制使用不便。#define主要用来创建快捷语法或条件编译指令,其在C++中的角色不同于定义常量。

(1) 一般用途的const变量,绝对不应该声明在头文件,定义在cpp里,尤其是基础类型(int之类)这个和inline函数是类似的,编译器能自动处理不同cpp中有同样const的问题;如果不使用const变量的地址,这个const变量最终会被完全优化掉,不占静态存储空间。而如果定义成extern,会导致编译器不得不为这个变量分配一个地址,并且在使用的时候强制地去从地址取得值,这会导致极大的性能下降。比如:


  
  1. const int a = 16;
  2. inline int sqr(x)
  3. {
  4. return a * a;
  5. }
  6. myFunc(sqr(a));

在这里,编译器可以把整个sqr(a)都优化掉,替换成一个立即数256。而如果a定义成了extern,这里就必须是读数值、乘法、传参数的过程了。
C++中编译器对于const变量做了充分的优化,它完全可以取代#define常量的一切功能。
比如:


  
  1. const int MAX_N = 100;
  2. int myArray[MAX_N];

在遇到使用const变量的时候,编译器如果已知const变量的值,就会直接把值代入进行优化,和#define是完全一样的。如果最后const变量没有取地址之类的操作,编译器就会认为这个变量没有被实际引用,于是在生成代码的最后把整个const变量去掉。
const变量如果不另加定义,默认就是static的。特意去定义成extern只会破坏编译器效率。这个和C是完全不同的,所以不要把C的法则想当然地用进来。
不过对于const变量类型是复杂类型(类)的时候,static的类型可能会导致每个cpp里面都生成一个对象,这时候应该考虑extern。

(2) const变量和#define宏相比最大的好处其实不在于类型检查,而在于可以有命名空间


  
  1. namespace MyNameSpace
  2. {
  3. #define myMacro 15
  4. class MyClass
  5. {
  6. public:
  7.     const static int myConst = 15;
  8. #define myMacro2 16
  9. }
  10. const int myConst2 = 16;
  11. }

myConst必须用MyNameSpace::MyClass::myConst来引用,myConst2对应MyNameSpace::myConst2,而#define的两个常量永远都是myMacro和myMacro2,这意味着#define的常量重名的可能性要大得多,而且很容易破坏OOP结构。

(3) 特殊情况下#define和const比可能会引起问题。比如函数重载:


  
  1. void myFunc(int x)
  2. {
  3. ...
  4. }
  5. void myFunc(short x)
  6. {
  7. ...
  8. }
  9. const short myConst = 128;
  10. #define myMacro 128
  11. myFunc(myConst);
  12. myFunc(myMacro);

#define由于没有类型,会去调用int版本的函数。这是const强制类型检查的好处

(4) const类型的编译效率比较好
因为编译器在编译的时候已经知道这个符号对应的是某类型的数了,编译会快一些。对运行影响不大。还有:


  
  1. #define MAXN (12*14)
  2. const int MAX_N = 12 * 14;

使用MAXN的时候,编译器每次都得对表达式求值;MAX_N的话,只求了一次。

(5) const类型不容易出错
这个问题是老生常谈了,#define MACRO 12+13这种写法会出问题,必须加括号。const就没这个问题。

(6) enum
enum其实可以看做是定义了一族const变量。它们同样也有命名空间,同样也有变量类型(不过变量类型是enum XXX),额外的,enum定义的常量不会使用额外的内存空间。缺点在于:enum定义的常量,类型是enum XXX,不是int。虽然可以和int型数值无限制地转换,但毕竟不是int,使用上不是那么方便,比如不能直接做加减乘除之类。

(7) #define的优势
#define在C++中的作用一般已经不是定义常量或者宏了,如前文所说这些功能应该由const和inline函数来代替。#define在C++中可以用来定义一些快捷语法,或者是根据编译选项不同生成不同内容:
#define L(x) L##x
L("abcde") // L"abcde"

#ifdef _UNICODE
#define MyFunc MyFuncW
#else
#define MyFunc MyFuncA
#endif

这些功能目前还没有其他语法可以替代。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值