在各种C代码中,我看到如下定义的常量:
#define T 100
在C ++示例中,它几乎总是:
const int T = 100;
据我所知,在第一种情况下,预处理器将用100替换T的每个实例。在第二个例子中,T实际上存储在内存中。
在C ++中#define常量被认为是不好的编程习惯吗?
答案 0 :(得分:34)
在C ++中#define常量被认为是不好的编程习惯吗?
是的,因为所有的宏(#define
定义的)都在一个命名空间中,它们在任何地方生效。变量,包括const
- 限定变量,可以封装在类和名称空间中。
宏在C中使用,因为在C中,const
- 限定变量实际上不是常量,它只是一个无法修改的变量。 const
- 限定变量不能出现在常量表达式中,因此不能将其用作数组大小。例如。
在C ++中,使用常量表达式初始化的const
限定对象(如const int x = 5 * 2;
)是常量,可用于常量表达式,因此你可以而且应该使用它们。
答案 1 :(得分:7)
在第二种情况下,不要求T
存储在“内存中”,除非你做了类似的地址。所有变量都是如此。
第二个更好的原因是第一个会在预处理器阶段经常“消失”,因此编译器阶段永远不会看到它(因此在调试信息中不会给你)。但这种行为并非标准规定,而是通常的做法。
除了条件编译之外,几乎不需要使用#define
语句。单个常量可以使用const
完成,多个相关常量可以使用enum
完成,宏可以替换为inline
个函数。
答案 2 :(得分:3)
由于C和C ++中常量的概念之间的差异,在C中我们基本上被迫在大多数时间使用#define
(或enum
)。在大多数情况下,const
在C中不起作用。
但是在C ++中没有这样的问题,所以在C ++中依赖#define
d常量确实是不好的做法(除非你出于某种原因确实需要一个文本替换的常量)。
答案 3 :(得分:2)
是。至少,使用枚举。 const int
和enum
都将在编译时进行评估,因此您具有相同的性能。但是,它更干净,调试更容易(调试器实际上会知道T是什么),它是类型安全的,并且不太可能在复杂表达式中断。
答案 4 :(得分:1)
预处理器宏不尊重范围 - 它是一个简单的文本替换 - 而static const int blah = 1;
可以包含在命名空间中。编译器仍将优化这两种情况(除非你获取该变量的地址),但它的类型和范围安全。
答案 5 :(得分:1)
是。最大的原因是预处理器定义不遵守语言的范围规则,污染全局命名空间,更糟糕的是 - 它们甚至在像
这样的情况下被替换。x->sameNameAsPreprocessorToken
由于预处理器定义在文本级别被替换,因此变量的其他常规属性不适用 - 您可以获取int const的地址,但不能获取#define'd常量的地址。
正如其他人所说,您通常也会失去类型安全和调试能力。
答案 6 :(得分:0)
另一个很酷的观点是,编译器可以优化全局积分常数,使它们不占用任何空间(即内存)。因此,它们在使用时可以被视为文字常量,并且与基于#define
的常量一样最优,而不会出现所有预处理器问题。