Book. Effective C++ item2-尽量使用const, enum, inline替换#define
##常规变量
c++
里面的#define
后面的定义部分,是不算代码的一部分的。所以如果你使用#define
:
#define ASPECT_RATIO 1.653
你希望这个代号ASPECT RATIO
这个代号是能够被编译器加入到记号表(symbol table)里面,如果调试的时候,这个部分出现问题,能够很快的发现出来。但是很多时候我们的预处理器会把这个变量移除,只保留了一个1.653
的常量,如果Debug的时候这个常量出现了错误,你是很难定位到自己需要修改代码的地方的,这就会造成我们在使用中Debug的时候很不方便。我们可以使用另外的方式来定义
1 |
const double AspectRatio = 1.653; |
修改之后,AspectRatio这个常量肯定会写入到记号表里面,是可以被编译器找到的。另外使用#define
可能会造成我们的代码里面有很多的object code 为 1.653, 但是使用const
的方式,我们的代码里面就只会有一个AspectRatio
。
如果是常量指针(constant pointers), 由于我们的常量一般是定义在头文件
中的,所以我们需要将指针声明为const
。如:
const char* const authorName = "Scott Meyers";
这里可以修改为String
类型,使用String来存储字符串会比char*
更加的合适,可定义为const std::string authorName("Scott Meyers");
Class内部专属变量
问题:限制常量的作用域是在Class内部,这样就要将这个常量作为Class的一个membeer, 这样就能够确保这个常量至多只有一个实体,并且必须将其声明为static member
。
1 |
class { |
因为这里面static const int NumTurns = 5;
这是放在类的声明里面的,在这里就是一个变量的声明,并不是变量的定义,在内存里面是没有的。但是c++如果你在其他地方去使用的话,那是需要我们对这个进行先定义在使用的。如果要在其他地方使用,就需要提供一个定义:
const int GamePlayer::Numturns;
这个就可以放在你需要使用GamePlayer::NumTurns
这个变量的文件里面,放在*.cpp
文件里,而不是*.h
文件中。
注明:由于在类的声明中已经给GamePlayer::NumTurns
进行了赋值操作,所以在这里单独直接定义就可以调用声明进行赋值操作。
另外一种针对老式编译器不支持上述语法的解决方法:
1 |
//在头文件中 |
上面这种方式可能问题:class在编译区间需要一个class的长两只,就是编译器不允许
static const int a
完成初始设定,这样我们就要使用到the enum hack
的方式进行补偿。理论:一个属于enumerated type的数值是可以当成ints来使用的
1 |
class { |
说明: emum hack定义的内容,是不能够取地址的,取地址的操作是不合法的,而取#define的地址也是不合法的,但是取一个const的地址是合法的。如果不想让其他人获得这个pointer或者reference指向你的整数变量,enum就可以很好的实现这个功能。
emum
和#define
是绝对不会导致非必要的内存分配的。
实现宏定义
宏定义看起来像一个函数,但是不会导致函数的调用导致的额外开销,比如:
#define CALL_WITH_MAX(a,b) f((a) > (b) ?(a):(b))
首先,写这样的宏必须为所有的实参都加上小括号,否则其他地方调用的时候会出现问题。但即使加上了,如果你实现这样的代码:
1 |
int a = 5, b = 0; |
在调用之前,a会递增之后在去调用,并且是否递增取决与它和谁比较。
小结
- 对于单纯变量,使用const对象或者enums替换
#define
- 形如函数的宏,修改为inline函数替换#define
Book. Effective C++ item2-尽量使用const, enum, inline替换#define的更多相关文章
- 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
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
- NO.2: 尽量以const,enum,inline 替换 #define
1.首先#define 定义不重视作用域(scope),虽然可以#undef控制,但是不美观,还存在多次替换的问题,以及没有任何封装性. 2.const XXX_XX,保证其常量性以及可控的作用域,如 ...
- 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define
其实这个条款分成两部分介绍会比较好,第一部分是用const和enum替换不带参的宏,第二部分是用inline替换带参的宏. 第一部分:用const和enum替换不带参宏 宏定义#define发生在预编 ...
- 条款2:尽量以const, enum, inline替换#define
原因: 1. 追踪困难,由于在编译期已经替换,在记号表中没有. 2. 由于编译期多处替换,可能导致目标代码体积稍大. 3. define没有作用域,如在类中定义一个常量不行. 做法: 可以用const ...
- 条款02:尽量以const,enum,inline替换#define
目录 1. 总结 2. 使用const常量或enum替换宏常量 class外部的常量指针 class专属常量 1. 总结 对于单纯常量,最好以const常量或enum替换#define 对于宏代码段, ...
- 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 ...
- 条款2:尽量使用const ,enum,inline替换define
宁可使用编译器而不用预处理器 假设我们使用预处理器: #define ABC 1.56 这标识符ABC也许编译器没看到,也许它在编译器处理源码前就被预处理器移走了,于是“标识符”ABC没有进入标识符列 ...
随机推荐
- 创建Git仓库
创建Git仓库 一.什么是版本仓库 什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能 ...
- iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
iOS精选源码 APP启动视频 自定义按钮,图片可调整图文间距SPButton 一款定制性极高的轮播图,可自定义轮播图Item的样式(或只... iOS 筛选菜单 分段选择器 仿微信导航栏的实现,让你 ...
- Tarjan算法:求解无向连通图图的割点(关节点)与桥(割边)
1. 割点与连通度 在无向连通图中,删除一个顶点v及其相连的边后,原图从一个连通分量变成了两个或多个连通分量,则称顶点v为割点,同时也称关节点(Articulation Point).一个没有关节点的 ...
- 一条sql关联删除多张表数据
现有6张表存在关联关系,要删除主表则其他5张表关联数据也要一块删掉(单条sql多id批量删除) delete t1,t2,t3,t4,t5,t6 FROM rmd_v AS t1 LEFT JOIN ...
- iOS 之keychain详解(附有Demo)
iOS keychain是苹果用来保存用户私密数据的一个专业的SQLite数据库.保存的数据主要是一些轻量级的私密数据,比如用户密码,token(令牌)等,保存在这个数据库中的密码不会因为你卸载了ap ...
- Solving ordinary differential equations I(nonstiff problems),exercise 1.1
Solve equation $y'=1-3x+y+x^2+xy$ with another initial value $y(0)=1$. Solve: We solve this by using ...
- Perl语言入门:第九章 使用正则表达式处理文本 示例程序和代码
#! /usr/bin/perl use strict; use warnings; print "\n----------------------------------_substitu ...
- 深入理解Java接口
一.接口的特点 接口中可以有变量和方法,接口中的变量会隐式的指定为public static final变量(并且只能是public static final变量),而方法会被隐式的指定为public ...
- 基础篇七:默认配置语法(/etc/nginx/nginx.conf)
首选我们 vim nginx.conf 参照上图,我们看看nginx.conf 的个参数含义 我们再看看 /etc/nginx/conf.d/default.conf
- 看了这个Java实习生入职测试题后,幸亏我不是实习生
看了这个Java实习生入职测试题后,幸亏我不是实习生 一个Java实习生的入职测试题,你能答对几个? 今天在某APP中看到,有实习生放出的Java实习生入职测试题.看完之后,很庆幸自己不是实习生. 本 ...