1 C++最主要的四部分:
  1. C
  2. Object-Oriented C++: 面向对象
  3. Template C++:泛型编程
  4. STL
C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。
2 尽量以const, enum , inline替换 #define
2.1

#define ASPECT_RATIO 1.653
记号名称ASPECT_RATIO在被编译器识别之前,已经被预编译器替换为1.653了,所以名称ASPECT_RATIO有可能没进入记号表内。
解决方法:

const double AspectRatio = 1.653;

性能影响:
    对浮点常量而言,使用常量可能币使用#define导致较小量的码,因为预处理“盲目地将宏名称ASPECT_RATIO”替换为1.653。

2.2 关于const的一个知识点

若要定义一个char*字符串,必须写const两次

const char* const authorName = "Scott Meyers";

若替换为String对象则更好:

const std::string authorName("Scott Meyers");

2.3 class专属常量

static, 将常量的作用域限制于class内,且确保此常量至多只有一份实体。
class GamePlayer {
private:
static const int NumTurns = 5; //常量声明式
int scores[NumTurns]; //使用该常量
};
这里的NumTurns是个声明式,而不是定义式。一般情况下,这样做就足够了,声明并使用它,但是有两种情况需要你给出一个关于它的定义式:
1 取这个class专属常量的地址
2 编译器坚持要看到一个定义式
这时候就需要一个额外的定义式:
const int GamePlayer::NumTurns;   // 由于class常量已在声明时或得初值,因此定义时不可以再设初值。
如果旧式的编译器不支持“in-class 初值设定”,那么可以把初值的设定放在定义式中:
class CostEstimate {
private:
static const double FudgeFactor;
...
};
ConstEstimate::FudgeFactor = 1.35; // 位于实现文件内
2.4 enum hack

如果你的编译器不够优秀,不允许"static整数型class常量"完成“in class初值设定”,那么,就有必要认识一下enum hack。先看一下补偿的做法:

class GamePlayer {
private:
enum { EnumTurns = 5 };
int scores[NumTurns];
};

现在来正式认识一下enum hack:

1 enum hack的行为某些方面比较像#define而不是const,如:

  • 取一个enum的地址是不合法的,同样的,取一个#define的地址通常也不合法;
  • 不允许一个指针或者引用指向某个enum常量;
  • Enums和#defines绝不会导致非必要的内存分配。

2 实用主义: 事实上,“enum hack”是template metaprogramming(模版元编程)的基础技术。

2.5 形似函数的宏——>template inline函数

// 以a和b的较大值调用f

#define CALL_WITH_MAX(a, b) f ( (a)  > (b) ? (a) : (b) )

纵使我是一个很有耐心的人,但是有时候遇到更复杂的宏的时候也会有点抓狂。

需要铭记一件事就是,宏是一个经常出现不可思议的事情:

int a = 5, b = 0;
CALL_WITH_MAX( ++a, b ); // a被累加两次
CALL_WITH_MAX( ++a, b+10 ); // a被累加一次

神奇的事情就是,a的递增次数取决于“它被拿来和谁比较”。

解决办法: template inline函数

template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f ( a > b ? a : b);
}
小结:
  • 对于单纯常量,最好以const对象或者enum替换#define
  • 对于形似函数的宏, 最好改用inline函数替换#define
参考:
《Effective C++ 3rd》

Effective C++(1-2) 编译器替换预处理器的更多相关文章

  1. Effective C++ 条款二 用编译器替换预编译器

    /************************************************************************/ /* C++条款二:用编译器替换预编译器 */ / ...

  2. [Objective-C语言教程]预处理器(18)

    Objective-C预处理器不是编译器的一部分,而是编译过程中的一个单独步骤. 简单来说,Objective-C预处理器只是一个文本替换工具,它指示编译器在实际编译之前进行必要的预处理. 我们将Ob ...

  3. C语言笔记 10_文件读写&预处理器

    文件读写 上一章我们讲解了 C 语言处理的标准输入和输出设备.本章我们将介绍 C 程序员如何创建.打开.关闭文本文件或二进制文件. 一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节.C ...

  4. C和指针 第十四章 预处理器 头文件

    编写一个C程序,第一个步骤称为预处理,预处理在代码编译之前,进行一些文本性质的操作,删除注释.插入被include的文件.定义替换由#define定义的符号,以及确定代码的部分内容是否应该按照条件编译 ...

  5. 详解C/C++预处理器

     C/C++编译系统编译程序的过程为预处理.编译.链接.预处理器是在程序源文件被编译之前根据预处理指令对程序源文件进行处理的程序.预处理器指令以#号开头标识,末尾不包含分号.预处理命令不是C/C++语 ...

  6. C Primer Plus之C预处理器和C库

    编译程序前,先由预处理器检查程序(因此称为预处理器).根据程序中使用的预处理器指令,预处理器用符号缩略语所代表的内容替换程序中的缩略语. 预处理器不能理解C,它一般是接受一些文件并将其转换成其他文本. ...

  7. C和指针 (pointers on C)——第十四章:预处理器

    第十四章 预处理器 我跳过了先进的指针主题的章节. 太多的技巧,太学科不适合今天的我.但我真的读,读懂.假设谁读了私下能够交流一下.有的小技巧还是非常有意思. 预处理器这一章的内容.大家肯定都用过.什 ...

  8. CSS 预处理器中的循环

    本文由 nzbin 翻译,黄利民 校稿.未经许可,禁止转载! 英文出处:css-tricks.com 发表地址:http://web.jobbole.com/91016/ 如果你看过老的科幻电影,你一 ...

  9. Microsoft Visual C++ 6.0预处理器参考手册

    返回总目录 Microsoft Visual C++ 6.0 预处理器参考手册 目录引言........................................................ ...

随机推荐

  1. php array_flip() 删除数组重复元素

    在PHP中,用于删除数组中重复元素有一个可用的函数,那就是 array_unique(), 但是它并不是一个最高效的方法,使用array_flip() 函数将比array_uniqure()在速度上高 ...

  2. 命令行下 初识 redis 入门教程

    1. redis-cli 命令行进入redis set,get, setex,给键值设置过期时间 setex name 10 DOG //设置name键 为 DOG 10秒后过期. setnx,判断值 ...

  3. django notes 五:Writing models

    models 其实也没什么好说的,就是普通的 python 类 settings 中配置数据库连接 DATABASES = { 'default': { 'ENGINE': 'django.db.ba ...

  4. html中设置textbox的宽和高

    1.宽:width是不行的,而应该用size size=30,表示能输入30个字符 2.高:  style="height:50px"

  5. 在Linux上创建webrev[基于git]

    在Sun/Oracle工作了N(>12)年后,对webrev工具甚为喜欢,因为其易用性确实非常好.幸运的是,有工程师将webrev工具放到了GitHub上,而且支持git. 下面给出使用webr ...

  6. [转载]二叉树(BST,AVT,RBT)

    二叉查找树(Binary Search Tree)是满足如下性质的二叉树:①若它的左子树非空,则左子树上所有结点的值均小于根结点的值:②若它的右子树非空,则右子树上所有结点的值均大于根结点的值:③左. ...

  7. 解决java获取系统时间差8个小时 专题

    在WIN7下发现一些Java的程序获取系统时间比真实时间差了8个小时,怀疑是Java程序沿用了低版本的JDK,获取时间时取的GSM 0时区,而中国是GSM +8,所以查了8个小时,解决办法如下: 修改 ...

  8. Knockout.js Visible绑定

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  9. c#尽量使用条件属性(Conditional Attribute)

    至此我们应该对Attribute属性大体了解了.下面来看看条件属性(Conditional Attribute)到底是怎么回事. 1 [Conditional("DEBUG")]  ...

  10. [转]C# 6.0 的新特性

    本文的内容包括引入C#6.0中的新的语言特性有哪些. 还有已经被引入的代码名称为 “Roslyn”新编译器. 编译器是开放源码的,并且可以从 codeplex 网站的这个地址下载到源代码: https ...