条款02:尽量以const ,enum,inline 替换 #define

思路是这样的

用const来代替#define的好处有

1.1.例如 #define  A  1.666  ,#define的记号名称可能不会进入记号表(symbol table)内,所以当由于此常量导致编译错误的时候,我们获取的错误信息中只会出现1.666。如果这个#define定义在一个非你所写的头文件中,你可能在追踪1.666来自何处花费大量的时间。

2.对于浮点常量而言,使用常量可能比使用#define导致较小量的码。(这里的码是目标代码的意思  存在于 .o文件中)。涉及到编译原理,不是太懂目标码量大的影响。

目标文件包含着机器代码(可直接被计算机中央处理器执行)以及代码在运行时使用的数据,如重定位信息,如用于链接或调试的程序符号(常量和函数的名字),此外还包括其他调试信息。

3.#define并不注重作用域。一旦#define被定义,他就在其后的编译过程中有效(除非在某处被 #undef)。常量弥补了这一点。

4.本书中把宏这个概念理解为一种看起来想函数的#define。(和平常学的不同。。)例如#define CALL(a,b) f((a)>(b)?(a):(b)),这种做法会无脑的替换参数导致逻辑错误,例如CALL(++a,b),当a>b时,++a被调用了两次。

凡是这种情况就用inline(内联函数)替换#define

template
inline void call(const &a,const &b)
{
f(a>b?a:b);
}

有两种特殊情况值得说说

1.定义常量的char*-based(基于char指针的)字符串,要用两个const

const char* const authorName = ''Scott Meyers';

这里用string更好

const std::string authorName(“Scott Meyers”);


2.class的专属常量

这里有两种技巧介绍 “in-class初值设定”  和 “the enum hack”。

先看例子

class GamePlayer{
private:
static const int NumTurn=5;
int scores[NumTurns];
}
 
  这里在class里声明了一个常量。这里值得注意的是:如果class专属常量为static且为整数类型(ints,chars,bools),我们如果不取其地址,则可以不用给出其定义式。 
  

但如果编译器非要你提供定义式,那则需要在.cpp文件里加入其定义式

const int GamePlayer::NumTurns;//这里不能再次设初值

如果编译器不支持in-class初值设定,我们可以用 “the enum hack”来实现在class声明中给常量设定初值。理论基础是——一个枚举类型的数值可权充当ints被使用;

class GamePlayer{
private:
enum{ NumTurn=5 };//令NumTurn成为5的一个记号
int scores[NumTurn];
}

enum hack的特性:取其地址不合法;不会导致非必要的内存分配;



最后提一下可执行文件的生成

编译器以C++源文件为输入,生成目标文件(.o)  编译单元是一对.h,cpp文件,归档器以目标文件为输入,生成静态库(.lib),链接器以目标文件集和库为输入,生成可执行文件或动态库。

#include 就是调用各种库

http://www.cnblogs.com/skynet/p/3372855.html//静态库和动态库的区别、创建和使用。为什么要动态库,最简单的一个例子,大型游戏有时候更新只需要下很小的更新补丁,不需要把整个重新程序编译一次,说明游戏只更新了部分动态库。


你可能感兴趣的:(Effective,C++学习笔记)