当前位置: 首页 > article >正文

【Effective C++】条款2:尽量以const,enum,inline替换#define

一.const替换#define 

#define的两个缺点:

  1. 不便于调试,编译器看到的是宏替换后的值,报错时显示也是替换后的内容,不便于定位错误
  2. 目标代码中出现多个替换后的内容。因为宏替换在预处理阶段完成,宏是不会进入记号表的。

 替换方案:使用const

//#define ARPECT_RATIO 1.653;
const double ArpectRatio = 1.653;

用#define替换常量时的两种特殊情况:

1.定义常量指针

//#define NAME "Effective C++"
const char* const Name = "Effective C++";

2.定义特定于类的常量

将常量作用域限制在类中,并确保只有一个常量的副本,就必须设置为类的静态成员

class GamePlayer
{
	//#define NUMTURNS 5;//这是无效的,#define只是无脑替换,无法将将作用域限制在类的内部
	static const int NumTurns = 5;//静态成员变量声明
	int scores[NumTurns];//使用静态成员变量
};

通常情况下,C++要求为所使用的任何东西提供定义,但类的静态整数类型常量(如bool,int,char)是个特例,可以声明时就给初值,在不取它们地址地址的情况下,可以直接使用,不用提供定义。

如果你在声明时给了初值,定义时就不能给值了。如果声明时没有给初值,定义时就能给值了。

class GamePlayer
{
	//#define NUMTURNS 5;//这是无效的,#define只是无脑替换,无法将将作用域限制在类的内部
	static const int NumTurns = 5;//静态成员变量声明
	//使用静态成员变量
};

//const int GamePlayer::NumTurns = 6;//不允许的
const int GamePlayer::NumTurns;

二.enum替代#define

枚举类型的值可以在需要int的地方使用

class GamePlayer
{
	enum{NumTurns = 5};
	int scores[NumTurns];//使用枚举常量,枚举更像#define,不能取地址
};

三.inline替代#define

我们实现如下宏函数:

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) //f是一个函数

 尽管我们已经很小心了,为每个参数都加上了括号,但问题防不胜防:

int a = 5, b = 0;
CALL_WITH_MAX(++a, b);
CALL_WITH_MAX(++a, b + 10);

由于#define只是无脑替换,根据执行逻辑,第一个表达式a会被++两次,第二个a会++一次。这绝不是我们想要的结果,我们期望a无论如何只会++一次!!!

替代方案:模版+内联函数,既能获得宏的效率,又能保证函数行为可预测与类型安全

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


http://www.kler.cn/a/158373.html

相关文章:

  • leetCode 90.子集 II + 回溯算法 + 图解 + 笔记
  • FFmpeg的C++封装:FFmpegWrapper
  • vue form表单的封装--使用的是elementUI
  • 如何设计自动化测试脚本
  • VAE模型及pytorch实现
  • centos7.5插件xtrabackup下载
  • 【数据结构】链表OJ题(顺序表)(C语言实现)
  • 硬件开发笔记(十四):RK3568底板电路LVDS模块、MIPI模块电路分析、LVDS硬件接口、MIPI硬件接口详解
  • C/C++ 实现枚举网上邻居信息
  • nginx对多个服务器的高可用,容易出现鉴权失败
  • 二百一十二、Flume——Flume实时采集Linux中的目录文件写入到HDFS中(亲测、附截图)
  • Socket.IO 实现原理(一篇文章让你彻底弄懂即时聊天技术)
  • 算法通关村第一关—白银挑战—链表高频面试算法题—查找两个链表的第一个公共子节点
  • docker: Error response from daemon: failed to create shim task: OCI runtime
  • 5.清除SVN用户账号两种方式
  • 什么是网络可视化?网络可视化工具有用吗
  • java学习part37定制排序和自然排序
  • OpenCV实现手势音量控制
  • 【Qt开发流程】之对象模型1:信号和槽
  • Class Introduction and Tools Familiarization