欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-23 13:59:40
...

Effective C++ 中文版 第三版》读书笔记

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

简单地说就是“宁可用编译器替换预处理器”,因为或许 #define 不被视为语言的一部分。这正是问题所在,例如:

#define ASPECT_RATIO 1.653

记号名称 ASPECT_RATIO 也许未被编译器看见;也许在编译器开始处理源码之前它就被预处理器移走了。于是记号名称 ASPECT_RATIO 有可能没有进入记号表(symbol table)内。于是当你运用此常量但却获得一个编译错误的信息时,可能会带来困惑,因为这个错误信息也许会提到 1.653 而不是 ASPECT_RATIO。如果 ASPECT_RATIO 被定义在一个不是我们自己写的文件内,我们肯定对 1.653 以及它来自何处毫无概念,于是我们将因为追踪它而浪费大量不必要的时间。

解决之道是用常量替换上述的宏(#define):

const double ASPECT_RATIO = 1.653;

作为一个语言常量,ASPECT_RATIO 肯定会被编译器看到,当然就会进入记号表内。此外因为预处理器 “盲目地将宏名称 ASPECT_RATIO 替换为1.653” 可能导致目标码(Object code)出现多份 1.653,若使用常量 ASPECT_RATIO 绝不会出现这种情况。

当我们以常量替换 #define 时,

需要注意的问题一:定义常量指针。

1.若要定义一个常量的(不变的)char*-based 字符串,你必须写 const 两次:

  const char* const AuthorName = "Toby";

2.string 对象通常比 char*-based 更好一些,所以上面代码往往写成:

  const std::string AuthorName = "Toby";

需要注意的问题二:class 专属常量。
1 为了将常量的作用域限制于class内,你必须让它成为class的一个成员;
2 而为确保此常量至多只有一份实体,你必须让它成为一个static成员。

class Toby {
private:
    static const int AuthorAge = 30;
}

基于数个理由 enum hack 值得我们认识。第一,enum hack 的行为某方面说比较像 #define 而不像 const,有时候这正是我们需要的。例如取 const 的地址是合法的,但取一个 enum 的地址就不合法,而取一个 #define 的地址通常也不合法。如果你不想让别人获得一个 pointer 或 reference 指向你的某个整数常量,enum 可以帮你实现这个约束。enum 和 #define 一样绝不会导致非必要的内存分配。

有了 const、enum 和 inline,我们对于处理器(特别是 #define)的需求降低了,但并非完全消除。#include 仍是必需品,而 #ifdef/#ifndef 也继续扮演控制编译的重要角色。目前还不是预处理器全面隐退的时候,但是我们应该明确地将它们压在箱子底尽量不要用它们。

请记住:
1 对于单纯常量,最好以 const 对象或 enum 替换 #define
2 对于形似函数的宏(macro),最好用 inline 函数替换 #define