在C++中,为了避免魔法数,使用#define还是const更好?

4
使用 #define 和 const 有哪些优缺点?(反之亦然)当我阅读关于编程中的坏习惯,特别是魔法数字时,我发现自己更频繁地使用 #define。一些问题浮现在我的脑海中,比如:经常使用 #define 是否不好?它会占用内存空间吗?使用 const 会更快吗?
我已经阅读了一些关于这个问题的资料,但还不确定。据我所了解: #define 定义了一个宏(不确定宏的含义),与预处理相关。在代码被处理之前,它将定义关键字的所有实例替换为其他内容。而 const 则是一个变量,其值在运行时期间无法更改。
我能想到使用 const 的唯一原因是如果该值依赖于其他变量。例如:
#define PI 3.14159f
#define RADIUS 3.0f
#define AREAOFCIRCLE PI*RADIUS*RADIUS

如果每次使用AREAOFCIRCLE时,程序都要计算PI*RADIUS*RADIUS,那么效率会很低。相反:

const float areaofcircle = PI*RADIUS*RADIUS;

如果程序只计算一次,那么使用#define可能更有效率。

回到最初的问题,#define和const有什么区别?


可能重复:https://dev59.com/Km015IYBdhLWcg3w_Q4_?rq=1 - lolando
我已经阅读了那个内容,但我对所有答案都不满意。 - DarkPotatoKing
频繁使用 #define 是不好的吗?尽量不要使用它! - David Heffernan
constexpr怎么样? - Michael Gazonda
这个回答解决了你的问题吗?#define为什么不好,有什么适当的替代方案? - Thomas Weller
3个回答

10

不用担心效率问题,因为所有这些内容都将在编译时计算。

只要可能,您应该停止使用宏(至少停止用于定义常量)。宏与命名空间和作用域相冲突。另一方面,const对象具有类型,这可以减少意外错误。

阅读Stroustrup的建议总是很有用的:“那么,使用宏有什么问题?”


“all of them computes in compile-time.” 的意思是什么? - DarkPotatoKing
无论您使用宏还是const,PI*RADIUS*RADIUS的结果都将在编译时计算,并且最终值将被替换以进行赋值。 - masoud
那是否意味着 #define AREAOFCIRCLE PIRADIUSRADIUS 只会在程序中计算一次,而不是每次调用 AREAOFCIRCLE 都要重新计算? - DarkPotatoKing
是的,在运行时,您可以在使用“AREAOFCIRCLE”的任何地方获得计算出的值。 - masoud
用于定义清单常量的宏具有类型。 使用#define SIZE 1SIZE的类型为int - Pete Becker
@PeteBecker:是的,它们有默认类型,编译器选择它们而不是程序员想要的类型。然而,程序员可以通过 #define SIZE ((size_t)1) 插入实际类型,但这很丑陋! - masoud

4

"const"在C++中非常宝贵。常量可以强制执行表达式的类型检查,而“#define”定义的常量只是被扩展。

此外,由于常量是有类型的,编译器可以更好地推断优化,而使用#define时必须猜测(1.0是float还是double?使用后缀如1.0d或1.0f可能会有所帮助,但我很少看到实数被这样有意识地书写...)。

因此,请使用常量来定义常量。

const float PI = 3.14159f;
const float RADIUS = 3.0f;
const float AREAOFCIRCLE = PI*RADIUS*RADIUS;

您将至少获得相同的编译时优化+一些额外的类型检查。


3
"1.0" 表示双精度浮点数。没有什么需要猜测的。 - juanchopanza

-1
"

const

(常量)更加高效,因为它只占用一次内存并且可以在任何地方引用。相比之下,#define会占用空间,并且在使用时需要进行额外的操作。"

为什么 #define 会占用空间?我以为它只是进行文字替换而已? - DarkPotatoKing
当使用 #define 时,它可能会根据编译器产生附加操作。 - Alan Yang
我的意思是,当替换被使用时,它会占用内存。 - Alan Yang

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