Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;宏而不是常量_C++_C_Constants - Fatal编程技术网

C++ C/C++;宏而不是常量

C++ C/C++;宏而不是常量,c++,c,constants,C++,C,Constants,宏#define MAX 80相当于常量int MAX=80两者都是常量,无法修改 使用宏而不是常量整数不是更好吗?常量整数占用内存。宏的名称被其值替换为预处理器,对吗?这样就不需要记忆了 为什么我要使用const int而不是宏?1)调试是我的主要任务。调试器很难在运行时将MAX解析为该值,但它可以使用const int版本 2) 使用#define无法获取任何类型信息。如果您使用的是基于模板的函数;说std::max如果您的另一个数据是const int,则宏版本将失败,但const int

#define MAX 80
相当于
常量int MAX=80两者都是常量,无法修改


使用宏而不是常量整数不是更好吗?常量整数占用内存。宏的名称被其值替换为预处理器,对吗?这样就不需要记忆了

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

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

2) 使用#define无法获取任何类型信息。如果您使用的是基于模板的函数;说
std::max
如果您的另一个数据是
const int
,则宏版本将失败,但
const int
版本将不会失败。要解决这个问题,您必须使用
#定义最大80U
,这很难看

3) 您无法使用#define;它将应用于#define语句之后的整个编译单元。

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

namespace SomeNS {

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

}

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

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


还请注意,当编译器在使用
const
变量时可以访问该变量的定义时,允许它“内联”其值。因此,如果你从不记录它的地址,它甚至不需要占用空间。

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

如果有人试图对函数中的
MAX
进行阴影处理(如
const in MAX=32;
),当
MAX
是宏时,他们会收到一条非常奇怪的错误消息


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

实际上有几个原因:

  • 范围界定:不能为宏定义范围。它在全球范围内存在,周期为。因此,您不能有特定于类的常量,也不能有私有常量,等等。此外,如果您最终用一个宏的相同名称声明某个您甚至不知道存在的东西(在一些库/头中,您包括了f.e.),则可能会导致名称冲突

  • 调试:由于预处理器只是用宏的值替换宏的实例,因此很难知道为什么会出现特定值的错误(或者只是意外的特定行为…)。您必须记住该值的来源。在可重用代码的情况下,这一点更为重要,因为如果一个值被定义为一个未编写的头中的宏,那么您甚至不知道该值从何而来(因此,自己这样做不是很好)

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

  • 类型安全性:您可以为常量变量指定类型,而宏则无法指定类型


作为一般规则,我认为(在我看来)当你有一个明确的选择(即常量变量、枚举、内联线)时,你应该避免使用
#define
指令。

常量是类型安全的(er),给出更好的错误,并且编译器可以更好地优化它。“常量整数占用内存。宏的名称被其值替换为预处理器,对吗?这样就不需要记忆了。“嗯,宏值必须在asm中的某个位置,因此它肯定会占用内存。如果另一个值是
int const
,您确定
std::max
将无法编译吗?
80
也有type
int
(并且忽略顶级const)。如果另一个值不是
int
,它将无法编译,但在这两种情况下都是如此。允许com、编译器“内联”const的值,即使您使用了它的“地址”,并且编译异常失败“是的,但你必须担心的是,当宏被替换到你不希望的地方时,代码仍然会编译。有一个细微的区别:假设在头中,有一个类包含
std::vector v,以及一个内联函数,该函数执行
v.push_back(最大值)。如果
MAX
是一个宏,这很好,但是如果
MAX
是一个
int const
,这是一个未定义的行为(尽管我从未听说过一个实现失败)。@JonathanWakely你说得对,谢谢。已更新。@Agnew,因为它违反了一个定义规则。对于可以在多个翻译单元(在标题中)中定义的内容,标准要求它们由相同的标记序列组成,并且每个名称在查找时都绑定到同一实体(除非名称引用
常量,并且存在立即的左值到右值转换)。在
int const
中,const表示内部链接,这意味着每个翻译单元中有一个不同的实体。