# define的代价是什么?

5

如何定义常量?使用 #define 宏定义的方式是否是更常见和正确的方式?在编译、链接等方面,使用 #define 宏定义常量的成本是多少?还有其他成本更低的方式吗?


选择一种语言,任何一种语言? - Kyle Rosendo
1
C#不允许使用#define来定义常量。你可以使用#define DEBUG,但不能使用#define DEBUG 1。http://msdn.microsoft.com/en-us/library/yt3yck0x.aspx - Nathan Ernst
7个回答

14

定义任何常量的最佳方式是写

const int m = 7;
const float pi = 3.1415926f;
const char x = 'F';

使用#define是一种糟糕的C++编程风格。在命名空间范围内无法隐藏#define

比较:

#define pi 3.1415926

使用

namespace myscope {
const float pi = 3.1415926f;
}

第二种方法显然更好。


2
+1 #define 也是不好的风格,因为它没有向编译器提供任何明确的类型信息。 - GrahamS
2
这准确地概括了样式建议,但没有回答问题。以正确的C++风格声明的常量确实具有#defines所没有的成本。 - Dan Olson
1
@Dan Olson:啊,但是 #define 在代码大小方面也有代价,因为(根据编译器的聪明程度)你可能会引入许多文字常量,而一个单一的 const 就能实现相同的效果。 @Espuz:除非你在做非常底层的微处理器工作,否则不必担心任何一种代价。所以尽可能使用更好的风格,即 const - GrahamS
@Dan Olson,C++风格的常量(恰好是常量表达式)相比于#define有什么成本呢? - avakar
1
实际上,对于小整数来说,更好的方法是使用枚举{m = 7},因为您可以在编译时获取该值。 - Viktor Sehr
这是更好的,但如果没有解释,它仍然不够明显。 - Martin York

5

编译器本身不会看到 #define。预处理器在将宏传递给编译器之前会展开所有宏。然而,其中一个副作用是值被重复了...两个相同的字符串不一定是完全相同的字符串。如果您说

#define SOME_STRING "Just an example"

编译器在每次看到字符串时向输出文件添加一个副本是完全合法的。优秀的编译器可能会消除重复字面量,但这是它必须要做的额外工作。如果使用const,则编译器不必过多考虑这一点。


2
成本仅限于预处理器,在解析 #define 时(当然忽略处理充满常量 #define 的项目所需的额外调试成本)。

1

#define宏是由预处理器处理的,它们对编译器不可见。由于它们在编译器中不作为符号出现,因此很难调试涉及宏的内容。

定义常量的首选方法是使用const关键字以及正确的类型信息。

const unsigned int ArraySize = 100;

更好的是

static const unsigned int ArraySize = 100;

当常量仅在单个文件中使用时。


1

#define 会增加编译时间,但是执行时速度会更快...

通常在条件编译中使用 #define...

而 const 则用于一般数值计算中...

选择取决于您的需求...


1
使用 #define 定义常量,速度提升最多只会是微不足道的。如果编译器对常量进行了优化,那么就没有任何优势可言,而且你还会失去 const 带来的所有好处。 - JeremyP
是的... #define 在条件编译(跨平台应用程序中)非常方便... 这是唯一可以考虑的优点... - Mihir Mehta

0

#define 是字符串替换。因此,如果您在宏中犯了错误,它们将在后面显示为错误。大多数常见的错误类型或表达式不正确。

对于条件编译,预处理器宏效果最佳。对于其他要用于计算的常量,const 很好用。


0

CPU时间并不是使用#define或宏的成本。作为开发人员,成本如下:

  • 如果您的宏存在错误,编译器将在引用该宏的位置而不是定义该宏的地方标记它。
  • 您将失去宏的类型安全性和作用域。
  • 调试工具将无法知道宏的值。

这些事情可能不会消耗CPU周期,但它们会消耗开发人员的时间。

对于常量,声明const变量是更可取的,对于小型类型无关函数,优先使用内联函数和模板。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接