effective c++:尽量替换define,确保对象使用前初始化
#define ASPECT_RATIO 1.653
名为ASPECT_RATIO的值在预编译阶段被替换成1.653,如果在这个常量上出现编译错误,我们可能会困惑1.653的值是什么意思,于是将因为跟踪它而浪费时间。
我们需要使用一个常量来替换上述的宏
const double AspectRatio = 1.653;
当我们以常量替换#define 时,有两种特殊情况需要考虑
第一:常量指针的定义放在头文件内,需要被不同的源代码访问,因此有必要将指针声明为const,如:
const char* const authorName = "Scott Meyers"
或者写成c++形式:
const std::string authorName("Scott Meyers")
第二:为了将常量的作用域限制于class 中,必须让他成为class的一个成员,而为了确保此常量至多只用一份实体,需要声明为static:
class GamePlayer{
private:
static const int NumTurns = ;
int scores[NumTurns];
};
另一个常见#define误用的情况是以它实现宏max(a,b) f((a)>(b)? (a):(b)),该宏看起来像个函数,而且不会招致函数带来的额外开销。
但这往往会带来意想不到的结果:
int a = ,b = ;
max(++a,b);
max(++a,b+);
第一次调用max时a累加两次,而第二次调用max 时a累加一次,我想这应该不是编写这段程序的人的本意。
遇到上述问题,我们需要使用inline 来替换:
template <class T>
inline void max(const T& a,const T& b)
{
f(a>b ? a:b);
}
这样一来就不用操心参数被求值几次的问题了。
对象使用前初始化
对于无成员内置类型,必须手工完成初始化:
int x = ;
const char* text = "a c-style string";
double d;
std::cin >> d;
至于内置类型外的初始化需要在构造函数中完成,确保每个构造函数都将对象的每个成员初始化。
class PhoneNumber { ... };
class ABEntry { // ABEntry = “Address Book Entry”
public:
ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones);
private:
std::string theName;
std::string theAddress;
std::list<PhoneNumber> thePhones;
int numTimesConsulted;
};
ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
{
theName = name; // these are all assignments,
theAddress = address; // not initializations
thePhones = phones;
numTimesConsulted = ;
}
上面这段代码在构造函数体内对成员变量进行赋值,注意:这不叫初始化,真正的初始化是这样的:
ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
: theName(name),
theAddress(address), // these are now all initializations
thePhones(phones),
numTimesConsulted()
{}
这两个版本的构造函数在运行时效果一样,但后者往往效率更高,基于赋值的构造函数在调用构造函数体前已经为成员变量设了初始值,函数体内又进行了一次赋值,从而造成程序运行成本增加。另一方面如果成员变量是const或references就不能赋值,必须在初始化时确定。
初始化的顺序最好按声明顺序来,避免出现不必要的错误,例如:初始化一个数组前,首先初始化数组长度。
对于初始化次序不确定的情况(对不同编译单元的non-local static),则需要以local static替换之。所谓的local static对象指的是函数内的static 对象,其他则成为non-local static 对象。
假设有一个文件系统:
class FileSystem { // from your library’s header file
public:
...
std::size_t numDisks() const; // one of many member functions
...
};
extern FileSystem tfs; // declare object for clients to use
// (“tfs” = “the file system” ); definition
// is in some .cpp file in your library
其中tfs预留给客户使用,如果在客户使用tfs 之前,tfs还没有初始化,就会造成严重后果。
class Directory { // created by library client
public:
Directory( params );
...
};
Directory::Directory( params )
{
...
std::size_t disks = tfs.numDisks(); // use the tfs object
...
} Directory tempDir( params ); // 创建一个Directory对象
其中的tfs与tmpDir是不同人不同时间建立起来的,定义于不同编译单元内,这种情况下就无法保证tfs在tempDir之前被初始化。
我们需要做的就是把non-local static对象放到函数内变为local static,然后让用户调用该函数,这样就可以确保初始化的正确顺序。
class FileSystem { ... }; // as before
FileSystem& tfs() // this replaces the tfs object; it could be
{ // static in the FileSystem class
static FileSystem fs; // define and initialize a local static object
return fs; // return a reference to it
}
class Directory { ... }; // as before
Directory::Directory( params ) // as before, except references to tfs are
{ // now to tfs()
...
std::size_t disks = tfs().numDisks();
...
}
Directory& tempDir() // this replaces the tempDir object; it
{ // could be static in the Directory class
static Directory td( params ); // define/initialize local static object
return td; // return reference to it
}
effective c++:尽量替换define,确保对象使用前初始化的更多相关文章
- effective c++(04)之对象使用前初始化
对于内置类型以外的初始化责任落在构造函数身上.如下: class PhoneNumber{}; class ABEntry{ public: ABEntry( const string& na ...
- Effective C++ 之 Item 2:尽量以 const, enum, inline 替换 #define
Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 2. 尽量以 const, enum, inline 替换 #d ...
- Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
- Effective C++_笔记_条款02_尽量以const、enum、inline替换#define
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#d ...
- 《Effective C++》读书笔记 条款02 尽量以const,enum,inline替换#define
Effective C++在此条款中总结出两个结论 1.对于单纯常量,最好以const对象或enum替换#define 2.对于形似函数的宏,最好改用inline函数替换#define 接下来我们进行 ...
- 【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define
条款02: 尽量以 const, enum, inline 替换 #define 这个条款或许可以改为“宁可以编译器替换预处理器”. 编译过程: .c文件--预处理-->.i文件--编译--&g ...
- Effective C++阅读笔记_条款2:尽量以const,enum,inline替换#define
1.#define缺点1 #define NUM 1.2 记号NUM可能没有进入记号表,在调试或者错误信息中,无法知道1.2的含义. 改善:通过const int NUM = 1.2; 2.#dein ...
- Book. Effective C++ item2-尽量使用const, enum, inline替换#define
##常规变量 c++里面的#define后面的定义部分,是不算代码的一部分的.所以如果你使用#define: #define ASPECT_RATIO 1.653 你希望这个代号ASPECT RATI ...
- 【02】尽量以const,enum,inline替换#define
1.考虑为什么? 首先,#define不是语言的一部分,而是预编译过程.也就是在编译器编译之前,进行文本替换.考虑#define Pi 3.1425:在编译之前,Pi都会被文本替换为3.1415,因此 ...
随机推荐
- android ADB命令的使用
http://jingyan.baidu.com/article/fcb5aff7f55c63edab4a7174.html 综上所述,我觉得告知各位菜鸟同学如何删除自带的程序是很有必要的一件事情.1 ...
- 如何添加或删除ubuntu用户和组【转】
转自:http://blog.csdn.net/sin90lzc/article/details/7525670 在创建用户时,需要为新建用户指定一用户组,如果不指定其用户所属的工作组,自动会生成一个 ...
- C语言输出当前日期和时间
#include <stdio.h> #include <time.h> char* asctime2(const struct tm *timeptr) { static c ...
- Winform——计算器
namespace 计算器2._0 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } pr ...
- openfire源码分析
启动流程 Socket接口 Socket通信使用Mina框架实现,是XMPP协议的处理入口,具体为: 消息接收后由不同的节处理器处理: StanzaHandler基础消息类型,之后进行消息路由: 最后 ...
- 深入.NET平台和C#编程 错题录
1.在C#中,关于文件操作相关的类说法正确的是(AB) <选择二项> A:FileInfo类提供了用于操作文件的实例方法 B:File类提供了用于操作文件的静态方法 C:Directory ...
- OCJP考试介绍
OCJP考试介绍 考试名称:SCJP / OCJP / 1Z0-851 考试时间:150分钟 考题题目:60道题 通过条件:大于等于61%的题目正确 考点查询:http://www.pearsonvu ...
- hibernate不关闭session后果
(转自:百度知道) 看是怎么获得session的. 方法1: 通过配置监听器后,在Dao中用getCurrentSession获取(内部原理....),此时无需管理session的关闭与否: 方法2: ...
- swun 1388 你的背包
解题思路:这题给人的第一反应是背包,第二反应是贪心,我用的是搜索,枚举就可以,要有这种意识, 题目数据只有8个,暴力是可以解决的. #include<cstdio> #include< ...
- YouTrack Changing Database Location for EXE Distribution(windows service)
If you have installed YouTrack from EXE Distribution, then the best way to change the database locat ...