C++ 宏是否使代码更具可读性?
我就宏和它们的可读性进行了辩论。 我认为,在某些情况下,使用宏可以使代码更短、更容易理解、阅读更轻松 例如:C++ 宏是否使代码更具可读性?,c++,c,code-readability,C++,C,Code Readability,我就宏和它们的可读性进行了辩论。 我认为,在某些情况下,使用宏可以使代码更短、更容易理解、阅读更轻松 例如: #include <iostream> #define EXIT_ON_FAILURE(s) if(s != 0) {std::cout << "Exited on line " << __LINE__ << std::endl; exit(1);} inline void exitOnFailure(int s, int lineNu
#include <iostream>
#define EXIT_ON_FAILURE(s) if(s != 0) {std::cout << "Exited on line " << __LINE__ << std::endl; exit(1);}
inline void exitOnFailure(int s, int lineNum) {
if (s != 0) {
std::cout << "Exited on line " << lineNum << std::endl;
exit(1);
}
}
int foo() {
return 1;
}
int bar(int a, int b, int c) {
return 0;
}
int main() {
// first option
if (foo() != 0) {
std::cout << "Exited on line " << __LINE__ << std::endl;
exit(1);
}
if (bar(1, 2, 3) != 0) {
std::cout << "Exited on line " << __LINE__ << std::endl;
exit(1);
}
// second option
EXIT_ON_FAILURE(foo());
EXIT_ON_FAILURE(bar(1, 2, 3));
// third option
exitOnFailure(foo(), __LINE__);
exitOnFailure(bar(1, 2, 3), __LINE__);
return 0;
}
#包括
如果定义(Ex.In)失败(s),如果(s!=0){STD::CUTRealMe宏可以简化函数,使其更易于阅读。但是应该考虑使用内联函数代替.< /P>
在您的示例中,ExtIXON-OUTION,可以是内联函数。宏不仅使编译器ErOS不准确(它可能会导致一些ErrOS显示在错误的地方),但是在使用宏时有一些事情要小心,特别是变量,考虑这个例子:
#define MY_MACRO(s) if (s * 2 >= 20) foo()
// later on your code:
MY_MACRO(5 + 5);
虽然我可以调用foo(),但它不会,因为如果(10*2>=20)foo()
,它不会扩展到,如果(5+5*2>=20)foo()
,它会扩展到。所以在定义宏时,需要记住始终在变量周围使用()
宏也使程序更难调试。有时宏确实是您所需要的,但您应该尽量减少宏的数量。在您的示例中,已经有一个名为“assert”的宏,您可以使用它来代替创建新的宏
C++有很多特性,允许你在宏中不需要宏,C++中的宏应该比C++代码中的宏要少。
默认情况下指向你的脚。考虑下面的用法
您的宏:
if (doSomething())
EXIT_ON_FAILURE(s) /* <-- MISSING SEMICOLON! OH NOES!!! */
else
doSomethingElse();
将只对a
进行一次评估
#define DOUBLE(a) (a + a)
将计算a
两次。这意味着
x = DOUBLE(someVeryLongFunction());
如果DOUBLE是宏,则所用时间将是函数的两倍
另外,我(故意)忘记了在宏参数中插入括号,所以
这:
换句话说,您需要完美地编写一个宏,以便最小化
射中自己脚的机会如果你犯了错误,
你将为此付出多年的代价
尽管如此,是的,在某些情况下,宏会
代码更具可读性。它们非常少,但它们
存在。其中之一是assert
宏,您的代码重新创建了该宏。
对于复杂的系统来说,使用自己的定制是很常见的
assert
-与本地调试方案关联的类宏,以及
几乎总是使用宏来实现,以便获取\uuuu文件\uuu
,
\uuuuuu行\uuuuuu
和条件的文本
但即便如此,典型的assert
也是这样实现的:
#ifdef NDEBUG
# define assert(cond)
#else
# define assert(cond) __assert(cond, __FILE__, __LINE__, #cond)
#endif
换句话说,类似于宏的函数扩展为函数调用。
这样,当您调用assert
时,扩展仍然非常接近
它看起来像什么,参数展开的方式是
你会预料到的
还有一些其他用途。基本上,只要你需要,随时都可以
将信息从构建过程本身传递到程序,它将
可能需要通过宏系统。尽管如此,您
应尽量减少接触宏的代码量以及如何
宏有很多作用
最后一件事,如果你想使用宏,因为你认为
代码会更快,请注意这是魔鬼在说话
在过去,可能有一些情况下,转换小
宏中的函数显著提高了性能
尽管如此:
大多数编译器支持内联函数,有些甚至支持内联函数
自动转换为静态函数
现代计算机速度如此之快,你几乎肯定不会注意到
调用一个微不足道的函数的开销
只有当您的编译器不执行内联函数和时,您才能
将其替换为一个更好的,您已经验证了该函数调用
开销是一个瓶颈,您可能需要编写一些宏
如果你在C++中通过了代码,你可以对函数进行同样的处理。我可以说C++中的宏没有错误,另一方面,它们就像斑块:最好避免!单独的事实是,他们不遵循范围,应该是一个指示邪恶宏的可能的方式。我通常都是这样做的:一个函数,比如“代码> ExtEng失败”。ure
和宏退出\u ON_FAILURE`只传递参数加上\uuuu文件\uuuuu
,\uuuu行\uuuuuuu
和\uuuuu函数\uuuuu
@MFH它们是一块斑块?使用?我想你的意思是瘟疫。看起来你在重新发明assert()宏。有时您不想使用assert,因为它可能会吓唬您的用户。在这种情况下,信息输出可能会更好。@WhiteZebra他们应该害怕什么?assert背后的想法是在调试版本中使用它,以便在软件发布之前发现可预防的问题。正因为如此,assert宏被定义为no发布模式下的操作(请参阅)…+1“如果您想使用宏,因为您认为代码会更快,请注意这是魔鬼说话。”当您过早优化时,回答得很好!尤其是良好宏使用的示例(调试断言)。
DOUBLE(a << b)
#define DOUBLE(a) ((a) + (a))
#ifdef NDEBUG
# define assert(cond)
#else
# define assert(cond) __assert(cond, __FILE__, __LINE__, #cond)
#endif