【问题标题】:C/C++ macros instead of const [duplicate]C/C++ 宏而不是 const [重复]
【发布时间】:2013-06-17 13:31:56
【问题描述】:

#define MAX 80 等价于const int MAX = 80; 都是常量,不能修改。

用宏代替常量不是更好吗?常量整数占用内存。宏的名称被预处理器替换为它的值,对吧?所以它不会占用内存。

为什么我要使用 const int 而不是宏?

【问题讨论】:

  • const 是类型安全的(er),提供更好的错误,并且可以由编译器更好地优化。
  • "常量整数占用内存。宏的名称被预处理器的值替换为它的值,对吗?所以它不会占用内存。" 那么宏值必须在asm 在某个地方,所以它肯定会占用内存。

标签: c++ c constants


【解决方案1】:

原因 #1:范围界定。宏完全忽略范围。

namespace SomeNS {

enum Functor {
  MIN = 0
  , AVG = 1
  , MAX = 2
};

}

如果上面的代码恰好包含在MAX宏定义之后的文件中,它会很高兴地被预处理成80 = 2,并且编译失败。

此外,const 变量是类型安全的,可以使用常量表达式安全地初始化(无需括号)等。

还要注意,当编译器在使用const 变量时可以访问它的定义,它可以“内联”它的值。所以如果你从不取它的地址,它甚至不需要占用空间。

【讨论】:

  • com,piler 允许“内联” const 的值,即使您确实获取了它的地址
  • "并且编译失败" 是的,但是你必须害怕的是,当宏被替换到你不想要的地方时,代码仍然可以编译。
  • 有一个细微的区别:假设在标题中,您有一个包含std::vector<int> v; 的类和一个执行v.push_back( MAX ); 的内联函数。如果MAX 是一个宏,这很好,但如果MAX 是一个int const,这是未定义的行为(尽管我从未听说过它失败的实现)。
  • @JonathanWakely 你说得对,谢谢。已更新。
  • @Agnew 因为它违反了单一定义规则。对于可以在多个翻译单元(在标题中)定义的事物,标准要求它们由相同的标记序列 组成,每个名称在查找时都绑定到相同的实体(除非name 指的是const 并且有一个立即的左值到右值的转换)。在int const 中,const 意味着内部链接,这意味着每个翻译单元中的不同实体。
【解决方案2】:

其实有几个原因:

  • 作用域:您不能为宏定义作用域。它存在于全球范围内,时期。因此,您不能拥有特定于类的常量,不能拥有私有常量等。此外,如果您最终声明了与您甚至没有的宏名称相同的东西,您可能会遇到名称冲突知道存在(在某些 lib/header 中包含 f.e.)

  • 调试:由于预处理器只是用宏的值替换宏的实例,因此很难知道为什么会出现特定值的错误(或者只是特定行为你没想到...)。你必须记住这个值是从哪里来的。在可重用代码的情况下更为重要,因为如果它已被定义为您未编写的标头中的宏,您甚至无法理解值的来源(因此它不是很好)自己做)

  • 地址:一个 const 变量,嗯,一个变量。这意味着您可以传递它的地址(当需要 const 指针或 const 引用时),但不能使用宏

  • 类型安全:您可以为 const 变量指定类型,而对于宏则不能。

作为一般规则,我会说(在我看来)当您有明确的替代方案(即 const 变量、枚举、内联)时,您应该避免使用 #define 指令。

【讨论】:

    【解决方案3】:

    问题是它们不一样。宏只是预处理器的文本替换,而const 是普通变量。

    如果有人试图在函数中隐藏MAX(例如const in MAX = 32;),当MAX 是宏时,他们会收到一条非常奇怪的错误消息。

    在 C++ 中,语言惯用的方法是使用常量而不是宏。试图节省几个字节的内存(如果它甚至可以节省它们)似乎不值得为可读性付出代价。

    【讨论】:

      【解决方案4】:

      1) 调试对我来说是主要的。调试器很难将MAX 解析为运行时的值,但它可以使用const int 版本来解决。

      2) 您不会通过#define 获得任何类型信息。如果您使用的是基于模板的函数;说std::max,你的其他数据是const int,那么宏版本将失败,但const int 版本不会。要解决这个问题,您必须使用 #define MAX 80U,这很丑。

      3) 你不能用#define 控制范围;它将应用于#define 语句之后的整个编译单元。

      【讨论】:

      • 如果另一个值为int const,您确定std::max 将无法编译吗? 80 也有 int 类型(并且顶级 const 被忽略)。如果另一个值不是int,它将无法编译,但在两种情况下都是如此。
      猜你喜欢
      • 2013-03-07
      • 2017-08-29
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      相关资源
      最近更新 更多