ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

effective C++:尽量用 const 和 inline 而不用#define

2021-12-17 14:02:45  阅读:162  来源: 互联网

标签:const 常量 effective int TURNS C++ NUM 定义


这个条款最好称为:“尽量用编译器而不用预处理”,因为#define 经常被认

为好象不是语言本身的一部分。这是问题之一。再看下面的语句:

#define ASPECT_RATIO 1.653

编译器会永远也看不到 ASPECT_RATIO 这个符号名,因为在源码进入编译器

之前,它会被预处理程序去掉,于是 ASPECT_RATIO 不会加入到符号列表中。

如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指

的是 1.653,而不是 ASPECT_RATIO。如果 ASPECT_RATIO 不是在你自己写

的头文件中定义的,你就会奇怪 1.653 是从哪里来的,甚至会花时间跟踪下去。

这个问题也会出现在符号调试器中,因为同样地,你所写的符号名不会出现在

符号列表中。

解决这个问题的方案很简单:不用预处理宏,定义一个常量:

const double ASPECT_RATIO = 1.653;

这种方法很有效。但有两个特殊情况要注意。

首先,定义指针常量时会有点不同。因为常量定义一般是放在头文件中(许

多源文件会包含它),除了指针所指的类型要定义成 const 外,重要的是指针也

经常要定义成 const。例如,要在头文件中定义一个基于 char*的字符串常量,

你要写两次 const:

const char * const authorName = Scott Meyers;

另外,定义某个类(class)的常量一般也很方便,只有一点点不同。要把常

量限制在类中,首先要使它成为类的成员;为了保证常量最多只有一份拷贝,

还要把它定义为静态成员:

class GamePlayer {

private:

static const int NUM_TURNS = 5; // constant declaration

int scores[NUM_TURNS]; // use of constant

...

};

还有一点,正如你看到的,上面的语句是 NUM_TURNS 的声明,而不是定义,

所以你还必须在类的实现代码文件中定义类的静态成员:

const int GamePlayer::NUM_TURNS; // mandatory definition;

// goes in class impl. file

你不必过于担心这种小事。如果你忘了定义,链接器会提醒你。

旧一点的编译器会不接受这种语法,因为它认为类的静态成员在声明时定

义初始值是非法的;而且,类内只允许初始化整数类型(如:int, bool, char 等),

还只能是常量。

在上面的语法不能使用的情况下,可以在定义时赋初值:

class EngineeringConstants { // this goes in the class

private: // header file

static const double FUDGE_FACTOR;

...

};

// this goes in the class implementation file

const double EngineeringConstants::FUDGE_FACTOR = 1.35;

大多数情况下你只要做这么多。唯一例外的是当你的类在编译时需要用到

这个类的常量的情况,例如上面 GamePlayer::scores 数组的声明(编译过程中

编译器一定要知道数组的大小)。所以,为了弥补那些(不正确地)禁止类内进行

整型类常量初始化的编译器的不足,可以采用称之为“借用 enum”的方法来解

决。这种技术很好地利用了当需要 int 类型时可以使用枚举类型的原则,所以

GamePlayer 也可以象这样来定义:

class GamePlayer {

private:

enum { NUM_TURNS = 5 }; // the enum hack — makes

// NUM_TURNS a symbolic name

// for 5

int scores[NUM_TURNS]; // fine

...

};

另一个普遍的#define 指令的用法是用它来实现那

些看起来象函数而又不会导致函数调用的宏。典型的例子是计算两个对象的最

大值:

#define max(a,b) ((a) > (b) ? (a) : (b))

这个语句有很多缺陷,光想想都让人头疼,甚至比在高峰时间到高速公路去开

车还让人痛苦。

无论什么时候你写了象这样的宏,你必须记住在写宏体时对每个参数都要

加上括号;否则,别人调用你的宏时如果用了表达式就会造成很大的麻烦。但

是即使你象这样做了,还会有象下面这样奇怪的事发生:

int a = 5, b = 0;

max(++a, b); // a 的值增加了 2 次

 max(++a, b+4); // a 的值只增加了 1 次

这种情况下,max内部发生些什么取决于它比较的是什么值!

幸运的是你不必再忍受这样愚笨的语句了。你可以用普通函数实现宏的效

率,再加上可预计的行为和类型安全,这就是内联函数

inline int max(int a, int b) { return a > b ? a : b; }

不过这和上面的宏不大一样,因为这个版本的 max 只能处理 int 类型。但模板

可以很轻巧地解决这个问题:

template

inline const T& max(const T& a, const T& b)

{ return a > b ? a : b; }

这个模板产生了一整套函数,每个函数拿两个可以转换成同种类型的对象

进行比较然后返回较大的(常量)对象的引用。因为不知道 T 的类型,返回时传

递引用可以提高效率。

 

标签:const,常量,effective,int,TURNS,C++,NUM,定义
来源: https://blog.csdn.net/chen_jin_sheng/article/details/121994841

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有