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

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

在一些比较大的工程中,经常会用到很多全局常量,这些常量的声明方式有很多种。
比如:宏常量 #define XXXXX = 0x00
枚举常量 enum{ YYYYY = 0, ZZZZZ = 1 };
……
除此之外还有什么常量声明方式?
这些常量声明方式有什么优缺点?
在什么情况下该用哪种常量?

评论 (1) •   •  链接 •  2012-09-12 
  • 0
    const 声明, 和枚举比较常用,宏定义会出现不安全的特性。当然你可以用一些熟悉函数生成常量比如是圆周率pi就可以直接用反正切的得到pi的值,而且精度很高! –  chuanchuan608  2012-09-18
9个答案

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

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> a </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">16</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">inline</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> sqr</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">x</span><span class="pun" style="color: rgb(0, 0, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">return</span><span class="pln" style="color: rgb(0, 0, 0);"> a </span><span class="pun" style="color: rgb(0, 0, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);"> a</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L5" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L6" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L7" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">myFunc</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">sqr</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">a</span><span class="pun" style="color: rgb(0, 0, 0);">));</span></li></ol>

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

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> MAX_N </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">100</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> myArray</span><span class="pun" style="color: rgb(0, 0, 0);">[</span><span class="pln" style="color: rgb(0, 0, 0);">MAX_N</span><span class="pun" style="color: rgb(0, 0, 0);">];</span></li></ol>

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

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

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">namespace</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(43, 145, 175); font-weight: bold;">MyNameSpace</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="com" style="color: gray;">#define</span><span class="pln" style="color: rgb(0, 0, 0);"> myMacro </span><span class="lit" style="color: maroon;">15</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">class</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(43, 145, 175); font-weight: bold;">MyClass</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="pun" style="color: rgb(0, 0, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L5" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">public</span><span class="pun" style="color: rgb(0, 0, 0);">:</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L6" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">        </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">static</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> myConst </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">15</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L7" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="com" style="color: gray;">#define</span><span class="pln" style="color: rgb(0, 0, 0);"> myMacro2 </span><span class="lit" style="color: maroon;">16</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L8" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="pun" style="color: rgb(0, 0, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L9" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> myConst2 </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">16</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">}</span></li></ol>

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

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

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">void</span><span class="pln" style="color: rgb(0, 0, 0);"> myFunc</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> x</span><span class="pun" style="color: rgb(0, 0, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">...</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L5" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">void</span><span class="pln" style="color: rgb(0, 0, 0);"> myFunc</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">short</span><span class="pln" style="color: rgb(0, 0, 0);"> x</span><span class="pun" style="color: rgb(0, 0, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L6" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L7" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">...</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L8" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="pun" style="color: rgb(0, 0, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L9" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">short</span><span class="pln" style="color: rgb(0, 0, 0);"> myConst </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">128</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="com" style="color: gray;">#define</span><span class="pln" style="color: rgb(0, 0, 0);"> myMacro </span><span class="lit" style="color: maroon;">128</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">myFunc</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">myConst</span><span class="pun" style="color: rgb(0, 0, 0);">);</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);">myFunc</span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">myMacro</span><span class="pun" style="color: rgb(0, 0, 0);">);</span></li></ol>

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

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

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="com" style="color: gray;">#define</span><span class="pln" style="color: rgb(0, 0, 0);"> MAXN </span><span class="pun" style="color: rgb(0, 0, 0);">(</span><span class="lit" style="color: maroon;">12</span><span class="pun" style="color: rgb(0, 0, 0);">*</span><span class="lit" style="color: maroon;">14</span><span class="pun" style="color: rgb(0, 0, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> MAX_N </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">12</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(0, 0, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: maroon;">14</span><span class="pun" style="color: rgb(0, 0, 0);">;</span></li></ol>

使用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

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

评论 (0) •  链接 • 2012-09-16

宏定义可以叫做全局常量吗?这我倒不清楚了。它就是一个常量而已,而且理论上是没什么不好的,宏定义只是文本复制。
如果你说的是希望整个工程项目都能用到的常量,的确大部分都会用宏定义的方式定义出来。
而枚举常量在Linux的内核代码中也很常见,不过更多是出现于定义一个错误代码,即希望1是代码错误a,2是代表错误b,但是很少作为全局的常量来声明。
我看来实际上代码中会出现全局的常量的情况很少,(我指的是占内存空间的,不是说像宏定义那样的。)因为非得要定义一个全局的常量的话,将它用宏定义声明会好很多。印象中只见过没办法只能定义全局变量的,可能我读的代码量不多。

参考后面几位的答案,再确认了一番。
在C++里头确实不提倡用#define,然后对Effective C++说的,也小怀疑了一下,我觉得是这样的,对于一个可以成为立即数的常量来说(即大小小于寄存器可以存的数的大小),define还是有优势的,翻译成汇编就知道了,立即数不用另外开辟空间来存储,我觉得编译器会做好这个优化(Effective C++说的也不完全对啊!)。但是对于一个不能作为立即数的常量来说,编译器编译代码的时候,一定会在data段再开辟一段空间专门放这个常量,然后用到的时候就会寻址找到这个常量来使用,用define的时候,用多少次,data段内就会出现多少次,而用const来定义的时候,无论用多少次,data段内也只会有一次,所以节省了代码空间。

SunnyLee
编辑于  2012-09-12
评论 (5) •  链接 • 2012-09-12
  • 0
    这话怎么说?为什么说优化后更好呢?优化会处理什么呢?能稍微讲一下吗?谢谢! –  SunnyLee 2012-09-16
  • 0
    @SunnyLee 我后面答案里面大致写了。总的来说就是const的值会自动代入到使用的位置成为立即数,和inline函数有点像。而define在多大程度上避免重复计算,是和编译器有关的。 –  灵剑2012 2012-09-16
  • 1
    @SunnyLee 再就是复杂类型上的问题了,比如#define pairData (pair<int,int>(12,15)) 和 const pair<int,int> pairData = pair<int,int>(12,15); 如果定义成宏,每次使用的地方都要调一次构造函数;而对const来说,只要调用一次就够了。 –  灵剑2012  2012-09-16
  • 0
    你的答案说得太好了。。看来对C++还是不熟啊。。还有对编译器实际做的工作确实还是有不清楚的地方。 –  SunnyLee  2012-09-16
显示更多隐藏的评论

1)宏不是全局常量,只是预编译,编译器在编译前做字符串替换。

2)C++中用const声明常量 const type name = value; 这个比宏好的是:其有类型检查。

3)enum 不是定义常量语义,是一种定义只能有某种取值类型语义。

4)全局变/常量千万不要定义在头文件中,而是declare在h文件,define在c/cpp文件中,如:

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="com" style="color: gray;">//t.c</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);">  g_int </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="lit" style="color: maroon;">10</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="com" style="color: gray;">//t.h</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">extern</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">const</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> g_int</span><span class="pun" style="color: rgb(0, 0, 0);">;</span></li></ol>

5)全局变量/常量应该全部定义在一个文件中,如果定义在不同的文件中,那么编译器将无法保证初始化顺序。

下面的这种情况可能会让a初始异常。

<ol class="linenums" style="list-style-position: outside; margin: 0px; padding: 0px 0px 0px 10px; border: none;"><li class="L0" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="com" style="color: gray;">//a.c</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L1" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> a </span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> b</span><span class="pun" style="color: rgb(0, 0, 0);">*</span><span class="lit" style="color: maroon;">2</span><span class="pun" style="color: rgb(0, 0, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L2" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L3" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="com" style="color: gray;">//b.c</span><span class="pln" style="color: rgb(0, 0, 0);"></span>
</li><li class="L4" style="list-style: decimal; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; color: rgb(153, 153, 153); background-color: rgb(250, 250, 250);"><span class="pln" style="color: rgb(0, 0, 0);"></span><span class="kwd" style="color: rgb(0, 0, 139); font-weight: bold;">int</span><span class="pln" style="color: rgb(0, 0, 0);"> b</span><span class="pun" style="color: rgb(0, 0, 0);">=</span><span class="lit" style="color: maroon;">10</span><span class="pun" style="color: rgb(0, 0, 0);">;</span></li></ol>

6)全局的变量/常量最好放在namespace中,以防避免变量冲突。尤其是和local variable的冲突,编译器和运行都是不会出错的。

评论 (1) •  链接 • 2012-09-12
  • 1
    第四点不同意,除非要用const变量的地址来做判断,否则应该定义在头文件里面。定义在头文件里面就相当于inline了,用到const的地方才可以有充分的优化。 –  灵剑2012  2012-09-16

宏常量只是编译前的文本替换而已,没有类型检查,宏常量也不能调试。所以宏很容易引入错误。
#define PI 3.14159
如果改为 #define PI asdf //没有类型检查的 也不会报错。
const double PI = 3.14159;
使用 double area = PIrr; //类型安全
在C++ 中常量不要使用宏去定义,如果是常量 在c++可以使用const 常量 去代替C语言中的宏。

使用枚举常量的优点是有清晰的语意,并且同个枚举类型中的各个常量必须是有关联的。例如
enum Color {RED,GREEN}; 这样你就知道这些是代表颜色的值。不要定义不论不类的枚举类型例如:enum Color {LENGTH,RED}。枚举类型定义常量可以提高代码的可读性。

评论 (0) •  链接 • 2012-09-12

尽量少用宏,具体可参考《Effecitve C++》条款2:
最好以const对象或enums替换#defines

评论 (0) •  链接 • 2012-09-12

(1)#define pi 3.14 就是在编译的时候简单的替换,我觉得叫常数。
(2)常量和变量相对。变量可变,常量不可变。
(3)全局常量一般使用就是头文件声明,c/cpp定义。
(4)枚举变量主要就是给多个相似的名字编了几个号。只能是整形。

评论 (0) •  链接 • 2012-09-13

这是宏定义,不是常量,常量是const,防止被修改,宏变量方便统一,维护

评论 (0) •  链接 • 2012-09-12

《Effecitve C++》里建议用const

评论 (0) •  链接 • 2012-09-16

我个人观点是尽量少用,全局常量太多会污染命名空间的。

评论 (0) •  链接 • 2012-09-23

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值