#define 宏实现函数功能的问题

情形1

#define free_ptr(p) \
if(p) delete p; p = nullptr;

在调用free_ptr(p)的地方展开看这段代码:

if(p)
delete p;
p = nullptr;

其实判断条件if(p),只对delete p 有效。不管if(p)是否满足执行条件p =nullptr都会执行。这么写可能直观一点

if(p)
delete p;
p = nullptr;

显然这种操作和我们的意图是不一样的。

情形2

#define free_ptr(p) \
delete p; p = nullptr; Object* p = new Object;
if(p) free_ptr(p);

展开代码:

Object* p = new Object;
if(p)
delete p;
p = nullptr;

显然这种操作也是不符合我们意图的。

情形3

#define free_ptr(p) \
if(p){\
delete p; p = nullptr;\
} Object* p = new Object;
free_ptr(p);

展开调用代码:

Object* p = new Object;
if(p){
delete p;
p = nullptr;
}

可以实现意图。

情形4

#define free_ptr(p) \
do{\
delete p; p = nullptr;\
}while(0); Object* p = new Object;
if(p) free_ptr(p);

展开调用代码:

Object* p = new Object;
if(p)
do{
delete p;
p = nullptr;
}while(0)

显然使用do{...}while(0), 可以实现意图。

使用宏来实现一个函数的功能是危险的,这么做的时候需要十分小心。相比于宏,可能使用内联函数更为妥当。

template<typename T>
inline void free_ptr(T** p)
{
if(*p)
{
delete *p;
*p = nullptr;
}
}

#define 宏实现函数功能可能存在的问题的更多相关文章

  1. #define宏定义形式的"函数"导致的bug

    定义了一个宏定义形式的"函数": #define  SUM8(YY)\ {\ int Y = YY>>2;\ ...\ } 然后使用的时候,传入了一个同名的变量Y: i ...

  2. C语言宏定义和宏定义函数

    要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定 ...

  3. #define宏定义

    1 #define的概念  #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本.  该命令有两种格式:一种是简单的宏定义, ...

  4. iOS 7:漫谈#define 宏定义

           #define宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开 ...

  5. iOS 7:漫谈#define 宏定义(转)

    iOS :漫谈#define 宏定义 #define宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步 ...

  6. C 语言宏定义函数编写时 do-while 的妙用和一些注意事项

    在 C 语言中,我们都知道可以用宏定义来编写函数,一般称为宏函数.如果一个宏函数比较复杂,那么在编写这样的宏函数是有一定技巧和注意事项的.文章给出一些我认为值得关注的地方,以及一些注意事项(个人建议) ...

  7. #define宏与const的区别

    1.#define宏的用法 #define用宏名代替一个字符串,这样便于修改,提高了程序的可移植性.编译器在编译预处理时只对宏做文本替换,而不进行类型检查,所以替换后可能产生一些副作用. 带参数的宏类 ...

  8. c c++ #define 定义假函数

    #define   Add(a,b)   ((a)+(b)) #define Max(a,b) ((a)>(b)?(a):(b)) 这就定义了一个假的函数 说白了就是字符串替换 这样在写代码时能 ...

  9. [ 随手记 1 ] C/C++宏,普通函数,内联函数

    函数定义 C 语言中的函数定义的一般形式如下: return_type function_name( parameter list ) { body of the function } 在 C 语言中 ...

随机推荐

  1. UVa 213 信息解码 (模拟 && 二进制)

    题意 :对于下面这个字符串 0,00,01,10,000,001,010,011……. 首先是长度为1的串,然后是长度为2的串,以此类推.不存在全为1的串. 你的任务是编写一个程序.首先输入一个代码头 ...

  2. Python3学习笔记(七):字典

    在python中,有一种通过名字来引用值的数据结构,这种类型的数据结构成为映射. 字典是Python中唯一内建的映射类型,具有以下特点: 字典中的值是无序的 值存在特定的键(key)下 键(key)可 ...

  3. [CSP-S模拟测试]:666(模拟)

    题目描述 不忘初心. 小$\pi$假期在家无聊,打开了某弹幕直播网站. 突然,有一个精彩的镜头. 小$\pi$看到了满屏的$6$,其中,有$666$.也有$666666$.也有$6666666666. ...

  4. Java缓存机制

    1 Java缓存 1.1 jvm内置缓存 Java中实现缓存的方式有很多,比如用static hashMap基于内存缓存的jvm内置缓存,简单不实用,保对象的有效性和周期无法控制,容易造成内存急剧上升 ...

  5. StringBuffer的s1.capacity()是多少?

    定义有StringBuffer s1=new StringBuffer(10);s1.append(“1234”)则s1.length()和s1.capacity()分别是多少? StringBuff ...

  6. 5.并发编程-synchronized 细节说明

    并发编程-synchronized 细节说明 1. synchronized-锁重入 & 异常释放锁 说明 * 关键字synchronized 拥有锁重入的功能,也就是在使用synchroni ...

  7. 运行Spark官方提供的例子

    去spark官网把spark下载下来: https://spark.apache.org/downloads.html 解压,可以看下目录: 其中examples目录下提供了java,scala,py ...

  8. fastJson对象转字符串首字母小写问题

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  9. 使用NSIS脚本制作一个安装包

    大部分人第一次看到NSIS脚本都是一脸懵逼的.因为它这个脚本的结构乍一看上去就非常奇怪,不作说明的话是看不懂的. 编写脚本命令的时候要非常注意,命令要按照规定写在脚本中不同的段落里,也就是说,命令的先 ...

  10. WAMP搭建与配置

    使用WampServer整合软件包进行WAMP环境搭建 WampServer是一款由法国人开发的Apache Web服务器.PHP解释器以及MySQL数据库的整合软件包.免去了开发人员将时间花费在繁琐 ...