• Effective C++ 条款02:尽量以const,enum,inline替换 #define


    换一种说法就是宁可以编译器替换预处理器

    举例

    #define ASPECT_RATIO 1.653
    
    • 记号ASPECT_RATIO也许从未被编译器看见;也许在编译起开始处理源码前它就被预处理器移走了,于是它并没有进入符号表,当出现编译错误的时候会提示1.653,但是不会提示ASPECT_RATIO。

    • 解决办法就是用一个常量替换宏(#define):

    const double AspectRatio = 1.653;
    

    常量替换宏的两种特殊情况

    1. 常量指针
    • 常量定义通常被放在头文件内(以便被不同的源码含入)
    • 常量的(不变的)char*-based:
    const char* const authorName = "Scott Meyers";
    const std::string authorName("Scott Meyers"); (C++最好用这种方式)
    
    2. class专属常量
    • 为了将常量的作用域限制于class内,必须让它成为class的一个成员;而为确保此常量至多只有一份实体,必须让它成为一个static成员:
    class GamePlayer  {
    private:
    	static const int NumTurns = 5;  // 常量声明式	
            int scores[NumTurns];           // 使用该常量
    }
    
    • 如果编译器坚持要看到一个定义式,那么就必须提供以下定义,并且把它放入实现文件而非头文件,因为class常量已在声明时获得初值,因此定义时不可以再设初值。
    const int GamePlayer::NumTurns;   // NumTurns的定义;
    
    • 无法利用#define 创建一个class专属常量,因为#define并不重视作用域(scope)。一旦宏被定义,它就在其后的编译过程中有效(除非在某处被#undef)。

    • 旧式编译器也许不支持以上语法,它们不允许static成员在其声明式上获得初值。此外所谓"in-class 初值设定",也只允许对整数常量进行。应该改成如下形式:

    class CostEstimate {
    private:
    	static const double FudgeFactor;  // static class 常量声明位于头文件
    };
    const double CostEstimate::FudgeFactor = 1.35;  // 位于实现文件内
    
    • 如果编译起不允许“static 整数型class常量”完成"in class 初值设定",可改用所谓的"the enum hack" 补偿做法。其理论基础是“一个属于枚举类型的数值可权充ints被使用”,见如下定义:
    class GamePlayer {
    private:
    	enum {NumTurns = 5}; 
    	int score[NumTurns];
    }
    

    用inline替换形似函数的宏(macros)

    // 以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被累加一次
    
    template<typename T>
    inline void callWithMax(const T& a, const T& b) { // 由于我们不知道T是什么,所以采用pass by reference-to-const
    	f(a > b ? a:b);
    }
    

    总结

    • 有了const,enum,inline,我们对预处理器(特别是#define)的需求降低了,但并非完全消除。#define仍然是必需品,而#ifdef/#ifndef也继续扮演控制编译的重要角色。

    请记住

    • 对于单纯常量,最好以const对象或enums替换#define
    • 对于形式函数的宏(macros),最好改用inline函数替换#define
  • 相关阅读:
    落花美眷,终究抵不过逝水流年,回忆我的2016,展望2017。
    如何对于几百行SQL语句进行优化?
    基于.NET Socket API 通信的综合应用
    数据库备份定期删除程序的开发。
    如何开发应用程序将客户服务器数据库的备份,下载到本地的云服务上?
    从大公司做.NET 开发跳槽后来到小公司的做.NET移动端微信开发的个人感慨
    asp.net mvc entity framework 数据库 练习(一)
    ASP.NET CORE小试牛刀:干货(完整源码)
    [开源].NET数据库访问框架Chloe.ORM
    SqlBulkCopy简单封装,让批量插入更方便
  • 原文地址:https://www.cnblogs.com/zhonghuasong/p/7266295.html
Copyright © 2020-2023  润新知