《C++覆辙录》——1.2:幻数

简介:

本节书摘来自异步社区出版社《C++覆辙录》一书中的第1章,第1.2节,作者: 【美】Stephen C. Dewhurst(史蒂芬 C. 杜赫斯特),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2:幻数

幻数,用在这里时其含义是上下文里出现的裸字面常量(raw numeric literal),本来它们应该是具名常量(named constant)才对:

class Portfolio {
  // ...
  Contract *contracts_[10];
  char id_[10];
};```
幻数带来的主要问题是它们没有(抽象)语义,它们只是个量罢了。一个“10”就是一个“10”,你看不出它的意思是“合同的数量”或是“标识符的长度”。这就是为什么当我们阅读和维护带有幻数的代码时,不得不一个个地去搞清楚每个光秃秃的量到底代表的是什么意思。没错,这样也能勉强度日,但带来的是不必要的精力浪费以及准确性的牺牲。

就拿上面这个设计得很差的表示公文包(`Portfolio`)的型别来说,它能够管理最多10个合同。当合同数愈来愈多的时候(10个不够用了),我们决定把合同数增加至32个(如果你对安全性和正确性很挑剔,那最好是改用STL中的`vector`组件)。我们立刻陷入了困境,因为必须一个个去检查那些用了`Portfolio`型别的源文件里出现的每一个字面常量“10”,并逐个甄别每个“10”是不是代表“最多合同数”这个意思。

实际情况可能会更糟。在一些很大的、长期的项目里,有时“最多合同数是10”这件事成了临时的军规,这个(远非合理的)知识被硬编码在某些根本没有包含`Portfolio`型别头文件的代码中:
`
for( int i = 0; i < 10; ++i )
  // ...`
上面这个“10”是代表“最大合同数”的意思呢?还是“标识符的最大长度”?抑或是毫不相干的其他意思?

一堆臭味相投的字面常量要是不巧凑在了一块儿,史上最有碍观瞻的代码就这么诞生了:

if( Portfolio *p = getPortfolio() )
  for( int i = 0; i < 10; ++i )
    p->contracts_[i] = 0, p->id_[i] = '0';`
现在维护工程师可有事做了。他们不得不在Portfolio型别中出现的毫不相关的、但正好值相同的两个“10”之间费劲地识别出它们各自的意思并分别处理6。当这一切头疼的事有着极为简单的解决方案时,我们真的没有理由不去做:

class Portfolio {
  // ...
  enum { maxContracts = 10, idlen = 10 };
  Contract *contracts_[maxContracts]; 
  char id_[idlen];
};```
在其所在辖域有着明确含义的枚举常量同时还有着不占空间,也没有任何运行期成本的巨大优点。

幻数的一个不那么显而易见的坏处是它会以意想不到的方式降低它所代表的型别的精度,它们也不占有相应的存储空间7。拿字面常量40000来说,它的实际型别是平台相关的。如果int型别尺寸的内存能把它塞下,它就是int型别的。要是塞不下呢,它就成了long型别的。要是我们不想在平台移植的当口引狼入室(试想根据型别进行的函数重载解析规则在这里能把我们逼疯的情形),我们还是老老实实地自己指定型别吧,这比让编译器或平台替我们做这件事要好得远:
``
const long patienceLimit = 40000;``
另一个字面常量带来的潜在威胁来源于它们没有地址这件事。好吧,就算这不是个会天天发生的问题,但是有的时候将引用绑定到常量是有其作用的。

const long *p1 = &40000; // 错误!②
const long *p2 = &patienceLimit; // 没问题
const long &r1 = 40000; // 合法,不过常见错误44会告诉你另一些精彩故事
const long &r2 = patienceLimit; // 没问题幻数有百害而无一利。`
②译者注:字面常量无法取址,它们没有地址。
请使用枚举常量或初始化了的具名常量。

相关文章
|
数据可视化
【TICA2020早班车】“录”在脚下,“智”在何方
阿里QA导读:早班车第7趟,距离TICA2020正式开幕只剩下【5天】了,核心专题已经带着大家一一看过了,今天小编要把期待值拉满,带大家预习压轴嘉宾谢涛老师的【智能化测试的趋势和展望】,上车坐稳,咱们发车啦~往期中奖的小伙伴尽快跟后台联系哈,团体票已备好,有需求可以钉钉扫码入群咨询哦!
125 0
【TICA2020早班车】“录”在脚下,“智”在何方
|
算法 Java C++
漫漫大学江湖录 - 爱与恨唯与工作更交织
前言 其实在18年11月有了华为,就已经宣告结束了大学校招历程,是时候写下总结了,再不写估计很多东西都忘了。 在一些程序员社区混久了,从别人的学习、求职、工作经历中越发感受到很多的正能量,也本着攒RP值的原则,向学弟学妹们,尤其和我非名校双非本科生学弟学妹们传递点正能量,因为博主也是非名校出身,而且在整个求职的过程中能够很明显地感受到名校学生那种得天独厚的优势,同样的实力,名校学生进入BAT等一线互联网企业确实要容易很多,即便技术很水,一样有华为等企业保底,而非名校的可能连简历筛选这关都过不了。
2505 0
我为什么而工作? 文/江湖一剑客
文/江湖一剑客 今天我们来讲一下工作的意义,以及工作、生活、人生的意义等相关话题。 首先,我们来想一个问题:你觉得人的一生该怎样度过呢? 你是想在悲伤苦痛中度过一生,还是想快乐地度过一生呢? 毫无疑问地,人性都是趋吉避凶,追求快乐幸福,挣脱苦痛的。
1507 0
|
设计模式 C#
|
设计模式 C#
|
C# 设计模式 程序员