(C++)为什么要尽量避免使用#define?

本文详细阐述了在C++编程中应避免使用#define的原因,包括作用域、地址、括号、数据类型及记号等问题,同时提出了const和inline作为替代方案。

(C++)为什么要尽量避免使用#define?


(第一次写博客,不好请见谅。知识点是从《C++编程语言99个常见编程错误》里看的)

#define 是C++中的一个为常量定义名称的预处理命令。一般情况下,其实并没有道理一定要使用#define,因为其总能带来一些麻烦。这篇博客主要是列举该命令的弊端,并讲述其他代替方案。
(有的从C转行C++的可能会建议你使用它,但是这里是C++,不是C

1. define 定义字面值常量的弊端:

第一:作用域问题

#define PI 3.1415926

PI没有作用域,所以可能出现这种情况:

//File: MathLibrary.hpp

//其他的一些代码...
#define PI 3.1415926
//还是其他的代码...

然后我们在一个程序里面使用这个库:

#include "MathLibrary.hpp"
//其他代码...
double aFunction(double Length)//返回半径为 Length 的圆的面积(懒得想名字了)
{
	const auto PI = 3.14;//PI不存在作用域,所以这行代码等价于 const auto 3.1415926 = 3.14;
	                     //而3.1415926是个右值,不能用于声明 & 定义。
	//其他的代码...
}

第二:地址问题

#define NUMBER 233
int* aPointer = &NUMBER;//&NUMBER 被预处理器改成 &233 ,而233是个右值,没有地址。

第三:括号问题

#define MY_NUMBER 1<<5
int aNewNumber = MY_NUMBER * 2;//多半是废物:预处理器把表达式改为1<<5 * 2,即1 << (5 * 2)

第四:数据类型问题

这个就不写代码了。

宏本来就没有数据类型。一般情况下没啥事发生,但是遇到函数重载就麻烦了(数据类型作为函数签名的一部分)。

第五:记号问题

const int NUMBER = 233;

假设我们使用NUMBER,结果用错了,编译器就会提示NUMBER使用错误。(傻子都知道)
但是#define呢?预处理器比编译器快一步处理代码,所以如果我们用#define,那么报错时编译器不可能见到NUMBER,只能见到233,所以编译器只会说233使用错误。如果NUMBER被封装,那么用户压根不知道233是啥,只能一脸懵逼。

/*==========分割线==========*/

上述就是用#define定义字面值常量的问题。
一般情况,我们可以用const来定义字面值常量。如果担心资源占用,可以用enum枚举。

2. 用#define定义伪函数的弊端:

第一:运算符优先级问题

#define YES_OR_NO(NUM) NUM ? "Yes" : "No" //忘记加括号了
std::cout << YES_OR_NO(n) << std::endl;//该语句被视为std::cout<< n ? "Yes" : "No" << std::endl;
                                       //即(std::cout<< n) ? "Yes" : ("No" << std::endl);

关键是这段代码一直报错,你却不知道有什么问题,因为一切都是如此完美。

第二:先替换,再运算

#include<iostream>
using namespace std;
#define OUT(N) (cout << (N) << ' ' << (N) << ' ' <<(N) <<endl) 
int main()
{
	int a = 0;
	OUT(a);//注意
}
//第五行代码等于
(cout << (a++) << ' ' << (a++) << ' ' <<(a++) <<endl)

a自增了3次。

第三:作用域操作问题

int age = 0;
#define YOUR_BIRTHDAY() (age++) //每次调用,age+1
int main()
{
	Age age(Dogs);//狗的年龄
	YOUR_BIRTHDAY(); //因为作用域,你的年龄变量被遮盖,所以最后狗的年龄自增了
}

/*==========分割线==========*/

所以,伪函数一般都没啥用(但有时候还是有点用的,比如代码涉及到__LINE__等预处理器指令时)。

一般建议使用inline代替#define,效率照样高。

总结
珍爱生命,远离#define。

(有错误在评论区指正。有问题欢迎提问,特别难的除外)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值