条款02:尽量以const, enum, inline替换#define

本文探讨了在编程中尽量避免使用宏定义的原因,包括可追踪性问题和潜在的冗余代码。建议使用const常量、枚举和inline函数作为替代方案。const常量提供了类型安全和作用域限制,枚举用于类似宏的整数常量,而inline函数则解决了形似函数宏的问题,同时保持了作用域和访问规则的完整性。
摘要由CSDN通过智能技术生成

尽量少使用宏定义,如果ASPECT_RATIO被定义在一个非你所写的头文件内,为了追踪它会浪费很多时间。作为一个语言常量,AspectRatio肯定会被编译器看到,当然就会进入记号表内。对于浮点常量(比如本例),使用常量可能比使用#define导致更小量的码,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”可能导致目标码(object code)出现多份1.653,如果改为常量AspectRatio绝不会出现相同的情况。

#define ASPECT_RATIO 1.653

//解决方法:
const double AspectRatio = 1.653;

当用const常量替换宏定义,有两种特殊情况:

  • 定义常量指针:由于常量定义式通常被放在头文件内,以便被不同的源码含入,因此有必要将指针(不只是指针所指的东西)声明为const。例如要在头文件内定义一个常量的char*-based字符串,必须写const两次。

    const char* const authorName = "Scott Meyers";
    
    //使用string对象更好
    const std::string authorName("Scott Meyers");
    
  • class专属常量:为了把常量的作用域新只在class内部,所以要让这个常量成为类成员。为了确保此常量至多只有一份实体,必须让它成为一个static成员

    class GamePlayer{
    private:
        static const int NumTurns = 5;   //常量声明式
        int scores[NumTurns];
    }
    

    注意,这里看到的是声明式,不是定义式,一般来说都应给出定义式。但是如果这个变量是class专属,而且是static,还为整数类型(ints, chars, bools),只要不取他们的地址,就可以声明并使用它们且不需要提供定义式。如果要取某个class专属常量的地址,就必须提供如下定义式:

    //这个式子会放入实现文件而非头文件。
    //由于这个常量声明时就有了初值,因此定义时不可以再设初值
    const int GamePlayer::NumTurns;
    

    btw, 我们不能用#define创建一个class专属常量,因为宏不重视作用域,一旦被宏被定义,在后面的编译过程就有效了,除非在某处用#undef. 宏不能用来定义class专属常量,也不能提供任何封装性。

用enums代替宏(仍对于单纯常量)

这是const行不通的情况下,一种备用方案。万一编译器(错误的)不允许static整数型class常量完成int class初值设定,就可以用enum hack的做法,因为属于枚举类型的数值可以充当ints被使用

class GamePlayer{
private:
    enum{NumTurns = 5}; 
    int scores[NumTurns];
}

enum hack的几个特点:

  • 更类似宏,因为取enum的地址,取#define的地址通常都不合法,而取一个const的地址是合法的。
  • 不想让别人获得一个指针或者引用指向某个整数常量时,就可以用enum。
  • enums和#defines绝对不会导致非必要的内存分配。
  • enum hack是模板元编程的基础技术。

用inline函数替代宏定义(形似函数)

对于形似函数的宏,最好用inline函数替代#define

//以a和b的较大值来调用f
#define CALL_WITH_MAX(a,b) f((a)>(b) ? (a) :(b))  //宏的所有实参都要加小括号

//但调用f之前,a的递增次数取决于它被用来和谁比较
int a=5, b=0;
CALL_WITH_MAX(++a,b);
CALL_WITH_MAX(++a, b+10);

//优化:写出template inline函数
//callWithMax是个真正的函数,遵守作用域和访问规则,所以一定可以写出一个类内的私有内联函数。一般,宏无法完成此任务。
template<typename T>
inline void callWithMax(const T& a, const T& b){
	f(a>b ? a: b);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值