【问题标题】:What is #define mostly used for in c++?#define 在 C++ 中主要用于什么?
【发布时间】:2014-08-07 00:20:39
【问题描述】:

我刚刚使用#define 来更改我的值,例如:

    #include <iostream>
    #include <string>

    #define Changed_num 100

    using namespace std;

    int main ()

    {
        cout<< Changed_num<< endl;
    }

但我听说没有#define 有更好的方法(另一种方法是什么?)

所以我让我问一下,那你为什么需要#define?它最常见的用途是什么?

【问题讨论】:

  • should not be used that way。使用constexpr int changed_num = 100;
  • 如果你只是定义一个数字,最好使用常量。 #define 确实很强大,但也有缺陷。所以在使用的时候一定要小心
  • @armanali 不应该反过来:它有缺陷但真的很强大? :)
  • 我发现它最常用于使代码更难阅读和调试。 :)

标签: c++


【解决方案1】:

一般来说:是的,你应该尽量避免#define(见C++ FAQ: Are you saying that the preprocessor is evil?

原因是#defines 由预处理器处理,这是在词法级别(全局),因此您可以控制#define 替换的效果 不是那么好,而且很可能适得其反(例如,由于您包含的标头包含标头,而标头中包含的标头包含带有#define 的标头,这会导致您的代码行为不端或根本无法编译)。

你应该使用什么?

  • 对于常量,常量(例如const int Changed_num=100)可以是变量,也可以是静态类属性。 (见:Why would I use a const variable / const identifier as opposed to #define? )。还要检查 C++11 中的 constexpr 新关键字。
  • 用于代码。您应该尝试编写代码(您知道)类、抽象......等等,而不是剪切和粘贴:D(这或多或少是#define)。在某些使用宏参数的情况下,您可以尝试将其替换为模板代码......在其他一些情况下,您仍然需要使用宏
  • 对于条件编译(@James Kanze 建议):您可以使用不同版本的头文件,放置在不同的包含目录中(并在编译时使用不同的 -I 选项进行选择)。

什么时候你还应该使用#define

  • 包括警卫
  • 在某些情况下,代码(但要非常注意缺点)。
  • 条件编译,例如多平台构建(同样,要非常清楚缺点)[但考虑使用上述不同包含目录的选项]

【讨论】:

  • 谢谢。您回答了我的两个问题是初学者可以理解的一种方式...感谢所有回答或评论的人:)
  • 使用#define 和条件编译不是平台依赖的好主意。代码中的 only #ifdef 应该是包含守卫。通过使用单独的函数,在单独的包含文件中,在由-I 选项确定的路径中,可以更好地处理平台依赖关系。
  • @JamesKanze 我添加了您的建议。但是我仍然保留使用#defines 的可能性。我觉得仍然存在使用该选项无法实现的情况,或者它会减少很多麻烦。
【解决方案2】:

对于常量值,使用const int Changed_num = 100; 优于#define Changed_num 100,因为您可以分配类型。例如,您可以const unsigned long Changed_num = 100,将其声明为#define 有点棘手。 (你可以做类似#define Changed_num 100ul 的事情,但不是那么明显。)

#define 的一种可能用途是作为日志记录宏的一部分,例如 boost::log。它们的优势是可以在调用它们时插入 __FILE____LINE__ 之类的东西。它们也用于代码生成,例如boost::foreach(已被c++11 中的基于范围的for 取代)或boost::python。但是,一般来说,您最好使用 [模板化] 函数,以便获得适当的类型安全性。

#define 的主要缺点是它是一把超重的锤子。如果您 #define 某事,您以后不能用局部变量或函数覆盖它。一个特别令人震惊的情况是Windows.h 其中#defines minmax,如果您尝试使用std:::min,则会出现编译器错误,除非您set NOMINMAX

【讨论】:

  • +1 / re “我希望我的常量命名更像CHANGED_NUM。” - 如果它仍然是#define,这是一个很好的建议,但如果它改为const(或constexpr/enum)就不好了。通常的做法是为预处理器定义保留多字符全大写标识符。
  • @TonyD 够公平的。我刚刚删除了“作为旁注,我更喜欢将我的常量命名为更像 CHANGED_NUM。”从我的回答。我确实喜欢让我的常量在视觉上脱颖而出,但我想现在这样做的现代方式有所不同。 (Google 风格指南显然推荐 kChangedNum。)
【解决方案3】:

在所示场景中,#define 的 C++ 等效项是 const。在内部,#define 不是由编译器使用,而是由 预编译器 使用,用于在代码实际发送到编译器之前对其进行修改。因此,在您的情况下,编译器实际上只能看到cout&lt;&lt;100&lt;&lt;endl;。使用const 是更好的做法,因为它实际上是type safe

#define 在 C++ 中最常见的用例是 include guards,以确保任何特定对象的头文件只包含一次。

亚军最有可能用于特定平台的编译/优化,请参阅this link 了解一些示例。

【讨论】:

  • 预编译器?还是预处理器?
  • @BryanChen 他们是同义词。从我在互联网上看到的预处理器是目前首选的名称,早在我的时代(我在 1991 年左右学习 C/C++)这个术语更常见,因为它们还没有完全集成。
  • @Niels:真的吗?我大约在同一时间学习了 C,当时就像今天一样,cpp 是 C Preprocessor。 ;-) 无论如何 +1。
  • 也许是不同的书,或者我只是变老了;)
  • 非常感谢朋友。我现在更好地理解#define 以及为什么应该使用它们......谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-12-14
  • 1970-01-01
  • 2017-03-20
  • 2018-03-29
  • 2010-12-11
  • 1970-01-01
  • 2012-07-18
相关资源
最近更新 更多