#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,确保对象使用前初始化的更多相关文章

  1. effective c++(04)之对象使用前初始化

    对于内置类型以外的初始化责任落在构造函数身上.如下: class PhoneNumber{}; class ABEntry{ public: ABEntry( const string& na ...

  2. Effective C++ 之 Item 2:尽量以 const, enum, inline 替换 #define

    Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 2. 尽量以 const, enum, inline 替换 #d ...

  3. Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define

    尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...

  4. Effective C++_笔记_条款02_尽量以const、enum、inline替换#define

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#d ...

  5. 《Effective C++》读书笔记 条款02 尽量以const,enum,inline替换#define

    Effective C++在此条款中总结出两个结论 1.对于单纯常量,最好以const对象或enum替换#define 2.对于形似函数的宏,最好改用inline函数替换#define 接下来我们进行 ...

  6. 【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define

    条款02: 尽量以 const, enum, inline 替换 #define 这个条款或许可以改为“宁可以编译器替换预处理器”. 编译过程: .c文件--预处理-->.i文件--编译--&g ...

  7. Effective C++阅读笔记_条款2:尽量以const,enum,inline替换#define

    1.#define缺点1 #define NUM 1.2 记号NUM可能没有进入记号表,在调试或者错误信息中,无法知道1.2的含义. 改善:通过const int NUM = 1.2; 2.#dein ...

  8. Book. Effective C++ item2-尽量使用const, enum, inline替换#define

    ##常规变量 c++里面的#define后面的定义部分,是不算代码的一部分的.所以如果你使用#define: #define ASPECT_RATIO 1.653 你希望这个代号ASPECT RATI ...

  9. 【02】尽量以const,enum,inline替换#define

    1.考虑为什么? 首先,#define不是语言的一部分,而是预编译过程.也就是在编译器编译之前,进行文本替换.考虑#define Pi 3.1425:在编译之前,Pi都会被文本替换为3.1415,因此 ...

随机推荐

  1. Git - Tutorial官方【转】

    转自:http://www.vogella.com/tutorials/Git/article.html#git_rename_branch Lars Vogel Version 5.8 Copyri ...

  2. Android eMMC Booting

    Android eMMC Booting Contents [hide] 1 eMMC binaries 1.1 Creating the GPT table 1.2 Modifying .IMG F ...

  3. 【HDOJ】5657 CA Loves Math

    1. 题目描述对于给定的$a, n, mod, a \in [2,11], n \in [0, 10^9], mod \in [1, 10^9]$求出在$[1, a^n]$内的所有$a$进制下的数并且 ...

  4. [HDOJ5583]Kingdom of Black and White(暴力)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5583 一个01串,求修改一个位置,使得所有数均为0或1的子串长度的平方和最大.先分块,然后统计好原来的 ...

  5. IntelliJ IDEA创建第一个Java小程序

    我尝试了汉化,会影响IDE部分功能. 其实IDE完全没必要汉化,就那么几个单词,不懂的话,就有道字典查一下吧. 汉化易于入门,不汉化一样可以使用. 我爱这个编辑器,非常之强大,就是比较占内存. 我爱这 ...

  6. How to use 'crontab' command on bitnami

    You can edit the cron file using the following command: $ sudo crontab -e You can add a new line lik ...

  7. Miller_Rabin (米勒-拉宾) 素性测试

    之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则 ...

  8. C#操作文件

    c# 操作txt文件 # 操作txt文件 c#创建文本 private const string FILE_NAME = "ErroLog.txt"; public static ...

  9. css中图片的四种地址引用

    URL: CSS中四种引用图片asset的方式:

  10. 【转】PWM占空比和分辨率

    占空比是接通时间与周期之比冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同占空比:就是输出的PWM中,高电平保持的时间与该PWM的时钟周期的时间之比,如一个PWM的频率是1000Hz, ...