序
总结出自己经常重复的工作,抽象简化它们,按照适合自己思维方式,整合成我们自己需要的。
偷懒就是尽可能的少写代码,实现我们需要的效果。
前两篇究其根本也是为了能够尽可能的少写代码,从而节省时间。
一切为了偷懒 看似调侃,其实就是我的本心。** (^▽^) **
所以开始我的偷懒之旅吧!
宏的特性
宏的原样展开特性,对于才接触或者不怎么喜欢使用宏的人来说,宏一般用来定义常量或者类型,仅此而已,比如:
#define PI 3.1415926
#define unsigned char uchar
或者实现一些简单的函数功能,因为没有类型,有时候类似模板一样,可以输入使用不同类型的参数,比如:
#define add(x,y) (x+y)
#define sub(x,y) (x-y)
#define mul(x,y) (x*y)
#define dev(x,y) (x/y)
我的偷懒方式
1、指针、返回值检查
平常判断指针,都会类似如下方式:
int ret = 3;
int *ptr = &ret;
if (ret == -1)
return;
if (ptr == NULL)
return;
可能带打印且有返回值,便于快速分析:
int ret = 3;
int *ptr = &ret;
if (ret == -1)
{
std::cout << "ret:" << ret << std::endl;
return;
}
if (ptr == NULL)
{
std::cout << "ptr:" << ptr << std::endl;
return false; // 或者 -1
}
可以如下实现:
#define check(var, value, ...) \
if (var == value) {\
logs(var);\
return __VA_ARGS__;\
}
使用方式如下:
void test1() // 无返回值
{
int ret = 3;
int *ptr = &ret;
check(ret , -1);
check(ptr, NULL);
}
int test2() // 有返回值
{
int ret = 3;
int *ptr = &ret;
check(ret, -1, 0);
check(ptr, NULL, false);
}
2、指针释放销毁
指针内存释放,一般用自带的 delete 或者有自己的释放函数,假设如 free(),则方式如下:
xxx *ptr = new xxx;
...
if (ptr != NULL)
{
delete ptr; // or free(ptr);
ptr = 0;
}
则可简单如下定义:
#define delptr(ptr) if (ptr) {delete ptr; ptr = 0;}
#define freeptr(fun, ptr) if (ptr) {fun(ptr); ptr = 0;}
对于集合型指针,则可直接如下定义:
#define delptrlist(list) for (int i = 0; i < list.size(); i++) delete list[i]; list.clear();
#define delptrset(list, type) foreach (type p, list) delptr(p); list.clear();
#define delptrset11(list) foreach (auto p, list) delptr(p); list.clear(); // 版本 >= c++11
3、单实例类
对于类中的一种特殊设计模式,有时候仅仅需要一个对象实例即可,可以直接简单实现如下:
#define Singleton(ClassName) \
static ClassName &instance() {\
static ClassName *m_instance = 0;\
if (m_instance == 0)\
m_instance = new ClassName;\
return *m_instance;\
}
在对需要单实例的类加上如下设置即可:
class CTest
{
public:
Singleton(CTest) // 添加单实例宏
~CTest();
void xxxx();
void yyyy();
private:
CTest();
};
使用方式如下:
CTest::instance().xxxx();
CTest::instance().yyyy();
更简洁的使用形式如下:
#define ctest CTest::instance()
ctest.xxxx();
ctest.yyyy();
4、用于数组校验
对于串口、网络数据收发时,常有一些数据计算校验计算,有的是和、有的是亦或,可以简单归纳如下:
#define calc(dat, len, opt) ({ \
uchar val = dat[0]; \
for (int i = 1; i < len; i++) \
val opt dat[i]; \
val; \
})
使用方式如下:
uchar dat[30];
...
uchar sum = calc(dat, 30, +=);
uchar xor = calc(dat, 30, ^=);
如果是集合,向量等形式,可以修改如下:
#define calcset(arr, opt) ({ \
uchar val = arr[0]; \
for (int i = 1; i < arr.size(); i++) \
val opt arr[i]; \
val; \
})
使用方式如下:
std::veroct<uchar> array;
...
uchar sum = calc(array, +=);
uchar xor = calc(array, ^=);
对于非 uchar 类型数据,小伙伴们是不是可以自己很容易扩展了呢!?