Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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++中的预处理器宏是 P.> C++社区非常害怕和回避。_C++_Macros_C Preprocessor - Fatal编程技术网

什么会使C++;预处理器宏是公认的开发工具吗? C++中的预处理器宏是 P.> C++社区非常害怕和回避。

什么会使C++;预处理器宏是公认的开发工具吗? C++中的预处理器宏是 P.> C++社区非常害怕和回避。,c++,macros,c-preprocessor,C++,Macros,C Preprocessor,然而,在一些情况下,这是不可能的 将宏视为预处理器可以以非常简单的方式-- --留给我一个问题,到底是什么使预处理器宏“邪恶”,或者,正如问题标题所说,需要从预处理器宏中删除哪些功能(或删除哪些功能),使它们成为一个“好”的开发工具(而不是每个人在使用它时都感到羞耻的填充)。(毕竟,Lisp语言似乎包含宏。) 请注意:这与#include或#pragma或#ifdef无关。这是关于定义我的宏(…)… 注:我不希望这个问题是主观的。如果您认为是这样的话,请随意投票将其转移给程序员。SE。宏有一个显

然而,在一些情况下,这是不可能的

将宏视为预处理器可以以非常简单的方式--

--留给我一个问题,到底是什么使预处理器宏“邪恶”,或者,正如问题标题所说,需要从预处理器宏中删除哪些功能(或删除哪些功能),使它们成为一个“好”的开发工具(而不是每个人在使用它时都感到羞耻的填充)。(毕竟,Lisp语言似乎包含宏。)

请注意:这与
#include
#pragma
#ifdef
无关。这是关于定义我的宏(…)…


注:我不希望这个问题是主观的。如果您认为是这样的话,请随意投票将其转移给程序员。SE。

宏有一个显著的特点——它们很容易被滥用,而且很难调试。你可以用宏写任何东西,然后宏就可以了,当一切都不起作用时,你就很难调试产生的代码

仅此一项功能就让人对是否以及如何使用宏执行任务三思而后行


不要忘记,宏在实际编译之前是经过扩展的,因此它们会自动忽略名称空间、作用域、类型安全性和大量其他内容。

宏被广泛认为是邪恶的,因为预处理器是一个愚蠢的文本替换工具,对C/C++几乎一无所知

宏是邪恶的四个很好的理由可以在中找到

在可能的情况下,模板和内联函数是更好的选择。我唯一能想到C++为什么仍然需要预处理器的原因是:<代码>包含了< /Calp>S和注释删除> < /P> 一个广受争议的优点是使用它来减少代码重复;但是,正如您从boost预处理器库中看到的那样,必须付出很大的努力来滥用预处理器来实现简单的逻辑,例如循环,从而导致难看的语法。在我看来,最好是用真正的高级编程语言编写脚本来生成代码,而不是使用预处理器

  • 宏不提供类型安全性
  • 参数执行两次的问题,例如#定义MAX(a,b)((a)>(b)?(a):(b))并将其应用于MAX(i++,y-)
  • 调试问题,因为它们的名称在符号表中不会出现

  • 宏最重要的一点是它们没有作用域,也不关心上下文。它们几乎是一个转储文本替换工具。因此,当您定义max(..)时,在有max的任何地方,它都会被替换;因此,如果有人在其头中添加了过度通用的宏名称,则它们往往会影响他们不打算影响的代码

    另一件事是,如果不小心使用,它们会导致代码很难读取,因为没有人能够轻松看到宏的计算结果,特别是当多个宏嵌套时

    一个好的指导原则是选择唯一的名称,在生成样板代码时,尽快取消对它们的定义,以免污染名称空间

    此外,它们不提供类型安全或过载

    有时,宏可以说是生成样板代码的好工具,例如借助boost.pp,您可以创建一个宏来帮助您创建枚举,如:

    ENUM(xenum,(a,b,(c,7)));
    
    这可能会扩大到

    enum xenum { a, b, c=7 };
    
    std::string to_string( xenum x ) { .... }
    

    类似于NDEUTG的AsjtType()需要更容易实现,如宏

    。C开发人员使用宏有很多用途,C++开发人员使用模板。 <> P>显然有一些有用的角落,但大多数时候,C语言的坏习惯是由那些相信有这样一种叫做C/C++ +<的语言的人应用到C++的。


    所以说“这是邪恶的”更容易而不是冒险让开发人员误用它们。

    强迫程序员对宏使用正确的命名…以及更好的工具来跟踪宏的替换将解决我的大部分问题。我不能说我到目前为止遇到了重大问题…这是你自己都会感到非常痛苦的事情,以后要学会特别小心。但他们迫切需要更好的集成与IDE、调试器的冲突。

    引用Paul Mensonides(该库的作者)的话,大多数预处理器滥用都来自误解:

    几乎所有 与误用预处理器相关的问题源于试图 使类对象宏看起来像常量变量,函数看起来像 宏调用看起来像底层语言函数调用。充其量, 函数类宏调用和函数调用之间的相关性 应该是偶然的。它永远不应该被认为是一个目标。那就是 这是一种从根本上被打破的心态

    由于预处理器很好地集成到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作为预处理器来生成代码,预处理器也可以做到这一点,并且它的优点是不需要额外的构建步骤。 还有,t