C++ 各种全局常量的声明方式的优缺点
2012-09-26 16:45
274 查看
(1) 一般用途的const变量,绝对不应该声明在头文件,定义在cpp里,尤其是基础类型(int之类)这个和inline函数是类似的,编译器能自动处理不同cpp中有同样const的问题;如果不使用const变量的地址,这个const变量最终会被完全优化掉,不占静态存储空间。而如果定义成extern,会导致编译器不得不为这个变量分配一个地址,并且在使用的时候强制地去从地址取得值,这会导致极大的性能下降。比如:
在这里,编译器可以把整个sqr(a)都优化掉,替换成一个立即数256。而如果a定义成了extern,这里就必须是读数值、乘法、传参数的过程了。
C++中编译器对于const变量做了充分的优化,它完全可以取代#define常量的一切功能。
比如:
在遇到使用const变量的时候,编译器如果已知const变量的值,就会直接把值代入进行优化,和#define是完全一样的。如果最后const变量没有取地址之类的操作,编译器就会认为这个变量没有被实际引用,于是在生成代码的最后把整个const变量去掉。
const变量如果不另加定义,默认就是static的。特意去定义成extern只会破坏编译器效率。这个和C是完全不同的,所以不要把C的法则想当然地用进来。
不过对于const变量类型是复杂类型(类)的时候,static的类型可能会导致每个cpp里面都生成一个对象,这时候应该考虑extern。
(2) const变量和#define宏相比最大的好处其实不在于类型检查,而在于可以有命名空间
myConst必须用MyNameSpace::MyClass::myConst来引用,myConst2对应MyNameSpace::myConst2,而#define的两个常量永远都是myMacro和myMacro2,这意味着#define的常量重名的可能性要大得多,而且很容易破坏OOP结构。
(3) 特殊情况下#define和const比可能会引起问题。比如函数重载:
#define由于没有类型,会去调用int版本的函数。这是const强制类型检查的好处
(4) const类型的编译效率比较好
因为编译器在编译的时候已经知道这个符号对应的是某类型的数了,编译会快一些。对运行影响不大。还有:
使用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
这些功能目前还没有其他语法可以替代。
const int a = 16; inline int sqr(x) { return a * a; } myFunc(sqr(a));
在这里,编译器可以把整个sqr(a)都优化掉,替换成一个立即数256。而如果a定义成了extern,这里就必须是读数值、乘法、传参数的过程了。
C++中编译器对于const变量做了充分的优化,它完全可以取代#define常量的一切功能。
比如:
const int MAX_N = 100; int myArray[MAX_N];
在遇到使用const变量的时候,编译器如果已知const变量的值,就会直接把值代入进行优化,和#define是完全一样的。如果最后const变量没有取地址之类的操作,编译器就会认为这个变量没有被实际引用,于是在生成代码的最后把整个const变量去掉。
const变量如果不另加定义,默认就是static的。特意去定义成extern只会破坏编译器效率。这个和C是完全不同的,所以不要把C的法则想当然地用进来。
不过对于const变量类型是复杂类型(类)的时候,static的类型可能会导致每个cpp里面都生成一个对象,这时候应该考虑extern。
(2) const变量和#define宏相比最大的好处其实不在于类型检查,而在于可以有命名空间
namespace MyNameSpace { #define myMacro 15 class MyClass { public: const static int myConst = 15; #define myMacro2 16 } const int myConst2 = 16; }
myConst必须用MyNameSpace::MyClass::myConst来引用,myConst2对应MyNameSpace::myConst2,而#define的两个常量永远都是myMacro和myMacro2,这意味着#define的常量重名的可能性要大得多,而且很容易破坏OOP结构。
(3) 特殊情况下#define和const比可能会引起问题。比如函数重载:
void myFunc(int x) { ... } void myFunc(short x) { ... } const short myConst = 128; #define myMacro 128 myFunc(myConst); myFunc(myMacro);
#define由于没有类型,会去调用int版本的函数。这是const强制类型检查的好处
(4) const类型的编译效率比较好
因为编译器在编译的时候已经知道这个符号对应的是某类型的数了,编译会快一些。对运行影响不大。还有:
#define MAXN (12*14) 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
这些功能目前还没有其他语法可以替代。
相关文章推荐
- C++ 各种全局常量的声明方式的优缺点?
- C++ 各种全局常量的声明方式的优缺点?
- C++ 各种全局常量的声明方式的优缺点?
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- 【转】C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- c++ 全局/局部变量/常量声明/定义(二)
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
- C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区