Effective C++ 02 以 const, emum, inline 替换 #define

0 总纲

宁可以编译器替换预编译
( 源文件 -> 预处理 -> 编译 -> 汇编 -> 链接 -> 可执行文件 link )

1 单纯常量替换

  • 以一个常量替换#define

Q:

#define ASPECT_RATIO 1.653
  1. 记号名称 ASPECT_RATIO 在预处理阶段被替换成 1.653,未被编译器看见,未计入符号表,会给调试带来麻烦
  2. 预处理器将 ASPECT_RATIO 盲目的替换成 1.653,可能导致目标代码出现多份1.653,代码量增多

解决之道

const double AspectRatio = 1.653;
  1. 作为一个常量,一定会被编译器看到
  2. 较小的代码量
  • 两种特殊情况

    • 定义常量指针

    Q:

    const char* const authorName = "Scott Meyers";
    
    1. 在头文件内定义一个常量的char*-based字符串,必须写const两次

    解决之道

    const std::string authorName("Scott Meyers");
    
    • class专属常量

    Q:

    1. 无法利用#define 创建一个class专属常量,因为其并不重视作用域,不能够提供任何封装性

    解决之道1

    class GamePlayer
    {
    private:
    	static const int numTurns = 5;
    	int scores[numTurns];
    }
    
    1. 在一个class内定义一个表示数组的大小(数组在编译期间必须知道其大小)的常量,需要用到static 和 const 的组合
    2. 只要不取其地址,就可以如上述声明并使用他们,无需提供定义式;但如果需要取其地址,必须另外提供定义式(在实现文件中)如下:
    const int GamePlayer::numTurns; //声明时已经赋初值
    

    解决之道2

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

    "the enum hack" 补偿法

    1. enum hack 的行为比较像#define, 取一个enum的地址不合法 且 不会导致非必要的内存分配

2 形似函数的宏替换

Q:
#define 实现看起来像函数的宏,优点不会招致函数调用带来的额外开销,但是会遭遇麻烦

#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
int a =5, b=0;
CALL_WITH_MAX(++a, b); //a被累加两次
CALL_WITH_MAX(++a, b+10); //a被累加一次

解决之道

template<typename T>
inline void callWithMax(const T& a, const T& b)
{
	f(a > b ? a : b);
}

template inline 函数 实现, 既可以获得宏带来的效率,有可以享有一般函数所有可预料的行为和类型安全

3 预处理真香时刻

我们对预处理器的需求降低了,但是并非完全消除
#include是必须品
#ifdef/#ifndef 扮演控制编译的重要角色

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值