《C++覆辙录》——1.3:全局变量

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

1.3:全局变量

很难找到任何理由去硬生生地声明什么全局变量。全局变量阻碍了代码重用,而且使代码变得更难维护。它们阻碍重用是因为任何使用了全局变量的代码就立刻与之耦合,这使得全局变量一改它们也非得跟着改,从而使任何重用都不可能了。它们使代码变得更难维护的原因是很难甄别出哪些代码用了某个特定的全局变量,因为任何代码都有访问它们的权限。

全局变量增加了模块间的耦合,因为它们往往作为幼稚的模块间消息传递机制的设施存在。就算它们能担此重任,从实践角度来说8,要从大型软件的源代码中去掉任何全局变量都几乎不可能9。这还是说他们能正常工作的情况。不过可不要忘了,全局变量是不设防的。随便哪个维护你代码的C++ 新手都能让你对全局变量有强烈依赖的软件所玩的把戏随时坍台。

全局变量的辩护者们经常拿它的“方便”来说事。这真是自私自利之徒的无耻之争。要知道,软件的维护常常比它的初次开发要花费更多时间,而使用全局变量就意味着把烂摊子扔给了维护工程师。假设我们有一个系统,它有一个全局可访问的“环境”,并且我们按需求保证确实只有“一个”。不幸的是,我们选择了使用全局变量来表示它:
`
extern Environment * const theEnv; `
我们的需求一时如此,但马上就行不通了。在软件就要交付之前,我们会发现,可能同时存在的环境要增加到两个、三个或是在系统启动时指定的或根本就是完全动态的某个数。这种在软件发布的最后时刻发生的变更实属家常便饭。在备有无微不至的源代码控制过程的大项目里,这个变更会引发极费时间、涉及所有源文件的更改,即使在最细小的和最直截了当的那些地方也不例外。整个过程预计要几天到几星期不等。假如我们不用全局变量这个灾星,只要5分钟我们就能搞定这一切:
`
Environment *theEnv();`
仅仅是把对于值的访问加了函数的包装,我们就获得了可贵的可扩充性。要是再加上函数重载,或是给予函数形参以默认值,我们就根本不要怎么改源代码了:
`
Environment *theEnv( EnvCode whichEnv = OFFICIAL );`
另一个全局变量引起的问题并不能一望即知。此问题的来源是全局变量经常要求延迟到运行期才进行的静态初始化。C++语言里如果静态变量用来初始化的值不能在编译期就计算妥当,那么这个初始化的动作就会被拖到运行期。这是许多致命后果的始作俑者(此问题非常重要,常见错误55专门来讨论此问题):

extern Environment * const theEnv = new OfficialEnv;  ```
如果改用函数或class来充当访问全局信息的掮客,初始化动作就会被延后,从而也就变得安全无虞了:

class Environment {
public:
  static Environment &instance();
  virtual void op1() = 0;
  // ...
protected:
  Environment();
  virtual~Environment();
private:
  static Environment *instance_;
  // ...
};`

// ...
Environment *Environment::instance_ = 0;

Environment &Environment::instance() { 
  if( !instance_ )
    instance_ = new OfficialEnv; 
  return *instance_;
}```
在上述例子中,我们采用了称为单件设计模式(`Singleton Pattern`)的一个简单实现10,以所谓“缓式求值”形式完成静态指针的初始化动作(如果一定要在技术上钻牛角尖的话,好吧,这是赋值,不是初始化)。是故,我们能够保证`Environment`对象的数量不会超过一个。请注意,`Environment`型别没有给予其构造函数public访问层级,所以`Environment`型别的用户只能用它公开出来的`instance()`成员函数来取得这个静态指针。而且,我们不必在第一次访问`Environment`对象之前就创建它11:

`Environment::instance().op1();`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值