Apparently C ++中的预处理器宏是
有理由担心并避开C ++社区。 p>
但是,有几种情况C++ macros are beneficial。
以非常简单的方式看待预处理器宏可以是extremely useful和can reduce repetitive code -
- 告诉我一个问题,究竟是什么让预处理器宏变得“邪恶”,或者正如问题标题所说,哪个功能(或删除功能)会需要从预处理器宏中使它们成为一个“好的”开发工具(而不是每个人在使用它时都感到羞耻的填充)。 (毕竟,Lisp语言似乎包含了宏。)
请注意:不关于#include
或#pragma
或#ifdef
。这大约是#define MY_MACRO(...) ...
注意:我不打算让这个问题具有主观性。如果您认为是这样,请随意投票将其移至程序员.S。
答案 0 :(得分:3)
宏被广泛认为是邪恶的,因为预处理器是一个愚蠢的文本替换工具,几乎不知道C / C ++。
可以在C++ FAQ Lite找到宏的邪恶的四个很好的理由。
如果可能,模板和内联函数是更好的选择。我能想到为什么C ++仍然需要预处理器的唯一原因是#include
和删除注释。
一个广泛争议的优点是使用它来减少代码重复;但正如您可以通过boost预处理器库看到的那样,必须付出很多努力来滥用预处理器以处理诸如循环之类的简单逻辑,从而导致语法丑陋。在我看来,最好用真正的高级编程语言编写脚本来代码生成,而不是使用预处理器。
答案 1 :(得分:1)
宏有一个值得注意的功能 - 它们很容易滥用,而且很难调试。您可以使用宏编写任何内容,然后宏是expanded into one-liners,当无效时,您将很难调试生成的代码。
单独使用该功能可以让人们思考是否以及如何使用宏来完成任务。
不要忘记在实际编译之前扩展宏,因此它们会自动忽略命名空间,范围,类型安全性和其他许多东西。
答案 2 :(得分:1)
宏最重要的是它们没有范围,也不关心上下文。它们几乎是转储文本替换工具。因此,当你#define max(....然后你所拥有的最大值被替换;所以如果有人在他们的标题中添加过于通用的宏名称,他们往往会影响他们不想要的代码。
另一件事是,如果不小心使用它们会导致很难读取代码,因为没有人能够轻易地看到宏可以评估的内容,尤其是当多个宏嵌套时。
一个好的指导方针是选择唯一的名称,在生成样板代码时,尽快#undef它们以免污染命名空间。
此外,它们不提供类型安全或超载。
有时宏可以说是生成样板代码的好工具,比如在boost.pp的帮助下你可以创建一个宏来帮助你创建如下的枚举:
ENUM(xenum,(a,b,(c,7)));
可以扩展到
enum xenum { a, b, c=7 };
std::string to_string( xenum x ) { .... }
需要对NDEBUG作出反应的assert()之类的东西通常也更容易实现为宏
答案 3 :(得分:1)
有很多用途,C开发人员使用宏,而C ++开发人员使用模板。
很明显,它们很有用,但大多数情况下C语言的不良习惯都适用于那些认为有这样一种叫C / C ++的语言的人
所以说“它是邪恶的”比冒险开发者滥用它们更容易。
答案 4 :(得分:1)
大多数预处理程序滥用来自误解,引用Paul Mensonides(Boost.Preprocessor图书馆的作者):
几乎所有人 与滥用预处理器有关的问题源于试图 使类似对象的宏看起来像常量变量和类似函数 宏调用看起来像底层语言函数调用。最好, 类函数宏调用和函数调用之间的相关性 应该是附带的。它永远不应被视为目标。那 是一种从根本上打破的心态。
由于预处理器很好地集成到C ++中,因此更容易模糊线条,并且大多数人看不到差异。例如,请某人写一个宏来将两个数字加在一起,大多数人会写这样的东西:
#define ADD(x, y) ((x) + (y))
这是完全错误的。通过预处理器运行:
#define ADD(x, y) ((x) + (y))
ADD(1, 2) // outputs ((1) + (2))
但答案应该是3,因为添加1到2是3.然而,编写宏来生成C ++表达式。不仅如此,它可以被认为是一个C ++函数,但它不是。这是导致滥用的地方。它只是生成一个C ++表达式,一个函数是一个更好的方法。
此外,宏根本不像函数那样工作。预处理器通过扫描和扩展宏的过程来工作,这与使用调用堆栈调用函数非常不同。
有时候宏可以接受生成C ++代码,只要它不会模糊线条。就像你使用python作为预处理器来生成代码一样,预处理器也可以这样做,并且具有不需要额外构建步骤的优点。
此外,预处理器可以与DSL一起使用,例如here和here,但这些DSL在预处理器中具有预定义语法,用于生成C ++代码。它并没有真正模糊线条,因为它使用不同的语法。
答案 5 :(得分:0)
答案 6 :(得分:0)
强制程序员为宏使用正确的命名...而更好的工具来跟踪宏的替换将解决我的大多数问题。我不能说我到目前为止已经遇到了重大问题......这是你自己烧的东西,并且学会以后要特别小心。但他们非常需要更好地与IDE,调试器集成。