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,因此 ...
随机推荐
- 动态网页制作PHP常用的正则表达式
匹配中文字符的正则表达式: [u4e00-u9fa5] 匹配双字节字符(包括汉字在内): [^x00-xff] 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) 匹配空行的正则表达 ...
- vb.net 写入文件同步锁
<SoapHeader("oHeader")> _ <WebMethod()> _ <ScriptMethod(ResponseFormat:=Res ...
- How to write a product backlog step by step
一般来说,制定发布计划是在尝试回答这个问题:“最晚到什么时候为止,我们可以交付这个新系统的1.0版本“ 下面是验收标准规则的一个例子: 1. 所有重要性>=100的条目都必须在1.0版中发布. ...
- POJ 1903 & ZOJ 2469 & UVA 1326 Jurassic Remains (部分枚举)
题意:给定n个只有大写字母组成的字符串,选取尽可能多的字符串,使得这些字符串中每个字母的个数都是偶数.n<=24 思路:直接枚举每个字符串的选或不选,复杂度是O(2^n).其实还有更简便的方法. ...
- poj - 2377 Bad Cowtractors&&poj 2395 Out of Hay(最大生成树)
http://poj.org/problem?id=2377 bessie要为FJ的N个农场联网,给出M条联通的线路,每条线路需要花费C,因为意识到FJ不想付钱,所以bsssie想把工作做的很糟糕,她 ...
- HibernateTools的使用
1. 到 Hibernate.org官网上 下载最新版的 Hibernate Tools,我用的是 HibernateTools-3.2.4.GA版 2. 将 下载下来的压缩包解压缩,里面会有 plu ...
- java 的UUID的具体用法
参照JDK public final class UUIDextends Objectimplements Serializable, Comparable<UUID> 表示通用唯一标识符 ...
- 【温故知新】c#异步编程模型(APM)--使用委托进行异步编程
当我们用到C#类许多耗时的函数XXX时,总会存在同名的类似BeginXXX,EndXXX这样的函数. 例如Stream抽象类的Read函数就有 public abstract int Read(byt ...
- hdu2847(暴力)
去年看的一道题目,但是竟然傻傻的用dfs+循环链表去做. 简直傻到爆. 不过现在做这题还是想了好久而且还有好几次WA,其实这题还是很水的.直接暴力枚举就行了,枚举的前提是要算好复杂度, 可以知道的是 ...
- HDU 4006 The kth great number【优先队列】
题意:输入n行,k,如果一行以I开头,那么插入x,如果以Q开头,则输出第k大的数 用优先队列来做,将队列的大小维护在k这么大,然后每次取队首元素就可以了 另外这个维护队列只有k个元素的时候需要注意一下 ...