【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define
条款02: 尽量以 const, enum, inline 替换 #define
这个条款或许可以改为“宁可以编译器替换预处理器”。
编译过程:
.c文件--预处理-->.i文件--编译-->.o文件--链接-->bin文件
如果你做出这样的事:
#define ASPECT_PATIO 1.653
记号名称 ASPECT_PATIO 从未被编译器看见;也许在编译器开始处理源代码之前它就被预处理器移走了。于是记号名称 ASPECT_PATIO 有可能没有进入符号表(symbol table)内。于是,当你运用此常量但获得一个编译错误信息时,可能会带来困惑。因为这个错误信息也许会提到 1.653 而不是 ASPECT_PADIO 。
解决之道是以一个常量替换上述的宏(#define):
const double AspectRatio = 1.653;
当我们以常量替换#define时,有两种特殊情况:
- 定义常量指针
const char * const authorName = "Scott Meyers";
//前一个 const 声明 authorName 是一个指向 char 类型的const对象的指针;
//后一个 const 声明 authorName 是一个指向 char 类型对象的 cosnt 指针。
- class 专属常量
class GamePlayer{
private:
static const int NumTurns = 5; //常量声明式
int scores[NumTurns]; //使用该常量
};
然而你所看到的是 NumTurns 的声明式而非定义式。通常C++ 要求你对你所使用的任何东西提供一个定义式,但 如果他是个 class 专属常量又是 static 且为整数类型(integral type,例如 ints, chars, bools),则需特殊处理。只要不取他们的地址,你可以声明并使用它们而无须提供定义式。
但如果你取某个 class 专属常量的地址,你就必须另外提供定义式如下:
const int GamePlayer::NumTurns; //NumTurns 的定义
当你的编译器不允许”static 整数型 class 常量 完成 in class 初值设定“,你可以将初值放在定义式:
class CostEstimate{
private:
static const double FudgeFactor; //static class 常量声明
//位于头文件内
}
//class 常量定义;位于实现文件内
const double
CostEstimate::FudgeFactor = 1.35;
然而,万事总有例外,当你在 class 编译期间需要一个 class 常量值,例如在上述的 GamePlayer::scores 的数组声明中(编译器坚持必须在编译期间知道数组的大小),而且你的编译器恰好不支持 ”static 整数型 class 常量 完成 in class 初值设定“,你可以改用所谓的“the enum hack”补偿做法:
class GamePlayer{
private:
//令NumTurns 成为 5 的一个记号名称,这就没问题了
enum { NumTurns = 5};
int scores[NumTurns];
};
另一常见的#define 误用情况是以它实现宏(macros)。宏看起来像函数,但不会招致函数调用带来的额外开销。
但是:
宏有着太多的缺点,代码晦涩难懂让人痛苦不堪。
inline 函数:可以带来宏的效率以及一般函数的所有可预料行为和类型安全性。
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
请记住:
- 对单纯常量,最好以 const 对象 或 enums 替换 #define.
- 对于形似函数的宏 macros, 最好改用 inline 函数替换 #define
【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define的更多相关文章
- 《Effective C++》读书笔记 条款02 尽量以const,enum,inline替换#define
Effective C++在此条款中总结出两个结论 1.对于单纯常量,最好以const对象或enum替换#define 2.对于形似函数的宏,最好改用inline函数替换#define 接下来我们进行 ...
- Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
- 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define
其实这个条款分成两部分介绍会比较好,第一部分是用const和enum替换不带参的宏,第二部分是用inline替换带参的宏. 第一部分:用const和enum替换不带参宏 宏定义#define发生在预编 ...
- NO.2: 尽量以const,enum,inline 替换 #define
1.首先#define 定义不重视作用域(scope),虽然可以#undef控制,但是不美观,还存在多次替换的问题,以及没有任何封装性. 2.const XXX_XX,保证其常量性以及可控的作用域,如 ...
- Effective C++阅读笔记_条款2:尽量以const,enum,inline替换#define
1.#define缺点1 #define NUM 1.2 记号NUM可能没有进入记号表,在调试或者错误信息中,无法知道1.2的含义. 改善:通过const int NUM = 1.2; 2.#dein ...
- Effective C++ -----条款02:尽量以const, enum, inline替换 #define
class GamePlayer{private: static const int NumTurns = 5; int scores[NumTurns]; ...}; 万一你的编译器(错误地)不允许 ...
- Effective C++之条款2:尽量以const enum inline替换 #define
本文的标题也可以改成“用编译器替换预处理器”: const double AspectRatio = 1.653; //最好使用上述代码替换下述代码: #define ASPECT_RATIO 1.6 ...
- 条款02:尽量以const,enum,inline替换#define
目录 1. 总结 2. 使用const常量或enum替换宏常量 class外部的常量指针 class专属常量 1. 总结 对于单纯常量,最好以const常量或enum替换#define 对于宏代码段, ...
- 条款2:尽量以const, enum, inline替换#define
原因: 1. 追踪困难,由于在编译期已经替换,在记号表中没有. 2. 由于编译期多处替换,可能导致目标代码体积稍大. 3. define没有作用域,如在类中定义一个常量不行. 做法: 可以用const ...
- 条款2:尽量使用const ,enum,inline替换define
宁可使用编译器而不用预处理器 假设我们使用预处理器: #define ABC 1.56 这标识符ABC也许编译器没看到,也许它在编译器处理源码前就被预处理器移走了,于是“标识符”ABC没有进入标识符列 ...
随机推荐
- MySQL设置允许用户远程登录
. //登录数据库 mysql -u root -pvmwaremysql>use mysql; //%为所有ip都可以远程访问 mysql>update user set host = ...
- Value cannot be null. Parameter name: source
下图主要想说.net抛错后的优先级, 错误1是根本原因,排第一位: 错误2里的方法包含了错误1,排第二位: 错误3就是整个Action了. 类似这样的错误,按照这样的顺序来解决bug,相信很受用.
- Slickflow.NET 开源工作流引擎基础介绍-.NET Core2.0 版本实现介绍 (转)
前言:.NET Core 是.NET Framework的新一代版本,是微软开发的第一个跨平台 (Windows.Mac OSX.Linux) 的应用程序开发框架(Application Framew ...
- kafka brokers配置参数详解
基本配置如下: -broker.id-log.dirs-zookeeper.connect Topic-level配置以及其默认值将在下面讨论. Property Default Descriptio ...
- CSS中的样式层叠机制Cascade
CSS中的样式层叠机制Cascade 一.样式冲突 样式冲突是CSS渲染过程要解决的一个关键问题,样式冲突主要由两个原因造成: 元素包含了不同对象所赋予的样式:浏览器.用户.作者.其中,浏览器样式 ...
- (生产)axios - 请求接口
参考:https://www.awesomes.cn/repo/mzabriskie/axios axios 介绍 基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中 ...
- <Android 基础(七)> DrawerLayout and NavigationView
介绍 DrawerLayout是Support Library包中实现了侧滑菜单效果的控件 android.support.v4.widget.DrawerLayout NavigationView是 ...
- APP常用检测
检测设备.微信平台和app是否安装 // 检测是否安装了APP var isappinstalled = (function () { ); }()), // 检测ios设备 isIOS = (fun ...
- Razor 语法糖常规用法
1.隐匿代码表达式 例: @model.name 会将表达式的值计算并写入到响应中,输入时采用html编码方式 2.显示表达式 例:@(model.name)会将输入@model.name字符串 3. ...
- 关于form的action路径填写
一:可以是相对路径: 1.action="<%=request.getContextPath() %>/html/index.html" <%=request. ...