【为什么】C++中的宏

C++宏的简单理解

C++中的宏是一种代码片段,可以被宏的值所替换。宏是用#define指令来定义的,用#undef指令来取消定义。宏有两种类型:类对象宏和类函数宏。

类对象宏就像一个常量,只不过不需要分配内存空间。

类函数宏就像一个函数,只不过不需要调用和返回。

大白话来说,宏就是一种让你写代码时更方便、更简洁、更灵活的工具

举例说明

假设你想定义一个宏,用来计算两个数的最大值。你可以这样写:

#define MAX(a,b) ((a)>(b)?(a):(b))

这就是一个类函数宏,它接受两个参数a和b,然后用三目运算符返回较大的那个。

当你在程序中使用这个宏时,比如写:

int x = MAX(3,5);

编译器会在编译之前把宏名替换成宏的定义,也就是:

int x = ((3)>(5)?(3):(5));

这样就可以得到x的值为5

类对象宏和类函数宏

  • 类对象宏是一个标识符,被一段代码片段所替换。它看起来像一个数据对象,比如一个常量。

例如,你可以这样定义一个类对象宏:

#define PI 3.14159

这样在程序中使用PI时,就相当于使用3.14159。

  • 类函数宏是一个标识符,后面跟着一对括号和一些参数,被一段代码片段所替换。它看起来像一个函数调用,但实际上不是。

例如,你可以这样定义一个类函数宏:

#define SQUARE(x) ((x)*(x))

这样在程序中使用SQUARE(5)时,就相当于使用((5)*(5))。

什么时候用宏呢

宏的使用场景一般是:
当你需要在编译时替换一些常量或表达式,而不是在运行时计算它们。
当你需要定义一些简单的操作,而不想为它们创建函数或模板。
当你需要根据不同的编译选项生成不同的代码,比如调试信息或条件编译。
当你需要使用一些特殊的语法或符号,比如变长参数或字符串化。
但是宏也有很多局限和风险,所以应该谨慎使用,并尽量用C++提供的其他特性来代替它们

那么C++提供了哪些特性可以代替宏呢?

C++提供了一些特性可以代替宏,比如:

用inline函数或模板来代替函数式宏,可以保证类型安全和编译优化。
用constexpr或const来代替常量宏,可以避免重复定义和命名冲突。
用using或typedef来代替类型别名宏,可以增加可读性和灵活性。
用enum class或namespace来代替枚举宏,可以提供作用域和强类型检查。
用if constexpr或模板特化来代替条件编译宏,可以实现编译时分支选择。
用字符串字面量或运算符重载来代替字符串化或连接宏,可以实现更自然的语法。

还有哪些情况是必须使用宏的呢?

宏在C++中的必要性已经大大降低了,但是还有一些情况是无法用其他特性替代的,比如:

当你需要定义一些编译器或平台相关的常量或标志,比如__FILE__或_WIN32。
当你需要使用一些预处理指令,比如#include或#pragma。
当你需要实现一些复杂的元编程技巧,比如BOOST_PP库。

宏和内联函数的区别

宏和内联函数有以下几个区别:

宏是由预处理器展开的,而内联函数是由编译器复制到调用处的。
宏必须在程序开始处定义,而内联函数可以在程序任何地方声明。
宏不能访问类的数据成员,而内联函数可以。
宏没有类型检查和返回类型,而内联函数有。
宏可能会导致副作用和错误,而内联函数不会。

代码示例

以下是宏和内联函数的一些代码示例:

// 定义一个宏,用于计算两个数的最大值 
#define MAX(a,b) ((a) > (b) ? (a) : (b))
// 定义一个内联函数,用于计算两个数的最大值 
inline int max(int a, int b) { return a > b ? a : b; }
// 调用宏和内联函数 
int x = 10; int y = 20; int z = MAX(x++, y++); 
// z = 21, x = 11, y = 22 
int w = max(x++, y++); 
// w = 22, x = 12, y = 23

可以看到,宏会导致x和y被增加两次,而内联函数不会。这是因为宏只是简单地替换文本,而不考虑副作用

为什么宏会导致x和y被增加两次?

这是因为在调用宏的时候,宏的参数会被直接替换到宏的定义中,而不会像函数一样先计算参数的值。所以,当你调用MAX(x++, y++)时,实际上相当于执行了以下代码:

((x++) > (y++) ? (x++) : (y++))

这样就导致了x和y被增加了两次。如果你想避免这种情况,你可以先把x和y的值存储在临时变量中,然后再调用宏。或者你可以直接使用内联函数,因为内联函数会先计算参数的值,然后再复制到函数体中。

详细解释:

首先,你定义了一个宏MAX,用于计算两个数的最大值。然后,你定义了两个变量x和y,分别赋值为10和20。接着,你调用了宏MAX(x++, y++),并把结果赋值给变量z。这时候,预处理器会把宏的参数x++和y++直接替换到宏的定义中,得到以下代码:

((x++) > (y++) ? (x++) : (y++))

这段代码是一个三元运算符,它的意思是如果x++大于y++,就返回x++的值,否则返回y++的值。注意这里的x++和y++都是后置自增运算符,它们会先返回原来的值,然后再增加1。所以我们可以把这段代码拆分成以下几步:

1.比较x++和y++的值。因为x和y分别是10和20,所以x++返回10,y++返回20。比较结果是false。

2.因为比较结果是false,所以执行三元运算符的第三部分:(y++)。这时候y已经被增加了1,变成了21。所以(y++)返回21,并且再次增加1。

3.把(y++)的结果赋值给z。所以z等于21。

4.因为执行完了三元运算符的第三部分:(y++),所以跳过第二部分:(x++)。但是这时候x已经被增加了1,变成了11。

5.代码执行完毕。

最终结果是z等于21,x等于11,y等于22(被增加两次)。

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值