一、C/C++语言中的各种变量
C/C++语言中 的变量(variable)根据其存储持续性(生命周期)、作用域(scope,可见性)和链接性(linkage)(参考《C++Primer Plus》或博客)可以分为(static)全局变量、静态局部变量和自动变量(临时变量)以及类的成员变量。代码中使用最频繁的一般是自动变量,它的生命周期从定义的时候开始,代码块(花括符)下边界结束,它的作用域也是在其所在的代码块中,此外,它没有外部链接性(不能跨编译单元)。类的成员变量与自动变量有点类似,不同的是它的范围不是代码块,而是整个类。此外可以参考博客:BSS段,数据段,代码段,堆和栈,从编译器对内存分配的角度来看各种变量类型。
在选择使用哪种变量的时候,一般第一考虑自动变量,然后再考虑类的成员变量,再然后考虑静态局部变量,最后考虑静态全局变量。当然每种变量都有其特定的应用范围,甚至是不可替代的功能。比如全局变量,它可以跨越编译单元,在整个程序中被使用。MFC中的the app就是这样的一个全局变量。另外,假设有一个这样的应用场景,我们的程序需要一个状态标志,它会在许多不同的编译单元和不同的类中被用到(读——获取状态,写——修改状态),这个时候我们就需要一个全局变量。
但是,使用全局变量也会产生一些风险:
1,名字冲突,特别是与系统自定义变量的名字冲突(如与“windows.h“中的变量名冲突)。不过这个可以很好的使用名称空间(namespace)来规避。
2,出现bug时,不易定位,且很难调试。全局变量是在进入main()函数之前初始化,在退出main()之后进行清理工作,不方便设断点。下面引入一个项目中的实际案例进行说明。
二、案例引入
项目成员C为一个GUI软件要实现一个中英文切换的功能,他采用的是在代码中定一个全局的map<string, string>,将待切换中英文信息放在一个map中,需要的时候,去map中查找并转换。C采用的是MinGW编译器,支持C++11的初始化列表,故他是这样定义这个map:
<span style="font-size:14px;">#ifndef SF_RFID_STRINGLINGUIST
#define SF_RFID_STRINGLINGUIST
#include <QMap>
#include <QString>
#define TR(strEn) getTrQString(strEn, g_bIsEn)
extern bool g_bIsEn;
const QMap<QString, QString> g_mapLinguist = {
{"Initializing...", QString::fromLocal8Bit("初始化中...")},
{"Fail to create instrument object !", QString::fromLocal8Bit("创建设备句柄失败!")},
{"Fail to load instrument library !", QString::fromLocal8Bit("载入仪器运行库失败!")},
{"Fail to initialize instrument !", QString::fromLocal8Bit("初始化仪器失败!")},
{"Fail to load calibration data !", QString::fromLocal8Bit("载入校准文件失败!")},
{"Succeed to initialize instrument !",