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. python-select异步IO

    #实现多任务在同一个线程切换 #!/usr/bin/python from socket import * from select import * from time import ctime so ...

  2. CPU漏洞补丁修复导致KeServiceDescriptorTable获取变更

    一.前言 2018年元旦,出现的cpu的漏洞,可以在windows环三直接读取内核数据,windows对该漏洞提供补丁,补丁增加了一个页表,对应的内核处理也增加了,接下来我们看下补丁修复的表象以及对K ...

  3. 通过 Docker Compose 组合 ASP NET Core 和 SQL Server

    目录 Docker Compose 简介 安装 WebApi 项目 创建项目 编写Dockfile Web MVC 项目 创建项目 编写Dockfile 编写 docker-compose.yml文件 ...

  4. FocusBI: 《DW/BI项目管理》之数据库表结构 (原创)

    关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. <商业智能教程>pdf下载地址 链接:https://pan.baidu.com/ ...

  5. 利用css实现搜索过滤

    无意中找到一种利用css就可实现的搜索过滤的方法,不得不说看了代码之后确实被惊艳到了,亏我之前面试还因为做这个功能做太慢而拖了后腿.在此记录下代码: <!DOCTYPE html> < ...

  6. IOS学习资源汇总

    昨天夜里在简书看到关于ios学习资源总结的文章,在这分享给大家. http://www.jianshu.com/p/b7c4a787a597?utm_campaign=hugo&utm_med ...

  7. 【angular5项目积累总结】http请求服务封装

    http.provider.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/co ...

  8. BTREE索引和HASH索引的区别

    从本质上理解,BTREE是一种有序树,而hash是无序的.所以最关键的区别在于: 1,BTREE可以用来做范围查询,比如大于,小于,而HASH索引仅在"=","IN&qu ...

  9. J2EE的体系架构

    J2EE是Java2平台企业版(Java 2 Platform,Enterprise Edition),它的核心是一组技术规范与指南,提供基于组件的方式来设计.开发.组装和部署企业应用.J2EE使用多 ...

  10. GridFS使用及配合nginx实现文件服务

    Mongodb下GridFS使用及配合nginx实现文件服务 一.GridFS简介 GridFS是mongodb下用来存储文件的一种规范,所有官方支持的驱动均实现了GridFS规范. Mongodb本 ...