全局对象和创建顺序 我还在学习C++。我有一个问题。假设您的项目具有始终存在的全局对象,例如apimager,并且所有其他模块都可以访问它(通过#include)。现在,我通过以下方式来实现:
标题:全局对象和创建顺序 我还在学习C++。我有一个问题。假设您的项目具有始终存在的全局对象,例如apimager,并且所有其他模块都可以访问它(通过#include)。现在,我通过以下方式来实现:,c++,qt,qtcore,C++,Qt,Qtcore,标题: class ApiManager : public QObject { Q_OBJECT public: explicit ApiManager(QObject *parent = 0); signals: public slots: }; extern ApiManager apiMng; 资料来源: ApiManager apiMng; 问题是其他对象在初始化时也需要访问,我注意到C++全局对象是按字母顺序创建的。我想知道你是怎么处理的?有什么诀窍吗?例如,在自
class ApiManager : public QObject
{
Q_OBJECT
public:
explicit ApiManager(QObject *parent = 0);
signals:
public slots:
};
extern ApiManager apiMng;
资料来源:
ApiManager apiMng;
问题是其他对象在初始化时也需要访问,我注意到C++全局对象是按字母顺序创建的。我想知道你是怎么处理的?有什么诀窍吗?例如,在自由Pascal世界中,每个类模块都有初始化
和终结
部分:
Type
TApiManager = class
end;
var ApiMng: TApiManager;
initialization
ApiMng := TApiManager.Create;
finalization
ApiMng.Free;
。。。项目模块的初始化
顺序可以在uses
子句中的项目源中进行排序(如C++中的#include
)。我知道有很多方法可以做到这一点(例如,用自定义命令初始化但是,从这个主题来看,QuxGlobal静态应该自动公开实例,但它不< P> C++世界中的好习惯是不惜一切代价避免全局对象——对象越本地化越好。p>
如果您绝对必须拥有全局对象,我认为最好的方法是在main中以自定义顺序初始化对象——明确初始化顺序。事实上,您正在使用qt是在main中初始化的另一个参数-您可能希望在任何其他QObject之前初始化QApplication(需要argc和argv作为输入参数)。全局对象的初始化顺序仅在转换单元中定义(在那里是从上到下的)。翻译单位之间没有保证。典型的解决方法是将对象包装到函数中并返回对本地对象的引用:本地对象在第一次调用函数时被初始化(并且在使用C++11时也是以线程安全的方式)。这样,全局访问对象的构造顺序可以以一种有用的方式进行排序ApiManager& apiMng() { static ApiManager rc; return rc; }
也就是说,不要使用全局对象。它们弊大于利。它们没有按字母顺序初始化,翻译单元之间的初始化顺序也没有定义,因为标准对此没有任何保证 为什么全局变量是邪恶的 应该避免使用全局变量有几个原因,但主要原因是它们极大地增加了程序的复杂性。例如,假设您正在检查一个程序,您想知道名为g_nValue的变量的用途。因为g_nValue是一个全局值,全局值可以在整个程序的任何地方使用,所以您必须检查每个文件的每一行!在一个包含数百个文件和数百万行代码的计算机程序中,您可以想象这需要多长时间 第二,全局变量是危险的,因为它们的值可以被调用的任何函数更改,程序员很难知道这会发生 为什么不必要时应避免使用全局变量 非局部性——当单个元素的范围受到限制时,源代码最容易理解。程序的任何部分都可以读取或修改全局变量,因此很难记住或解释每个可能的用法 没有访问控制或约束检查——程序的任何部分都可以获取或设置全局变量,任何关于其使用的规则都很容易被打破或忘记。(换句话说,get/set访问器通常优于直接数据访问,对于全局数据更是如此。)进一步说,缺乏访问控制极大地阻碍了在希望运行不可信代码的情况下实现安全性(例如使用第三方插件)。 隐式耦合——具有许多全局变量的程序通常在其中一些变量之间以及变量和函数之间具有紧密耦合。将耦合项分组为内聚单元通常会产生更好的程序 并发问题——如果多个执行线程可以访问全局,那么同步是必要的(而且常常被忽略)。当将模块与全局模块动态链接时,即使在几十个不同上下文中测试的两个独立模块是安全的,组合系统也可能不是线程安全的 名称空间污染——全局名称随处可见。当您认为您使用的是本地时(拼写错误或忘记声明本地),您可能会不知不觉地使用全局,反之亦然。此外,如果必须将具有相同全局变量名的模块链接在一起,如果幸运的话,将出现链接错误。如果你运气不好,链接器会简单地将同一名称的所有使用视为同一对象。 内存分配问题——某些环境具有内存分配方案,这使得全局分配变得棘手。在“构造函数”具有分配以外的副作用的语言中尤其如此(因为在这种情况下,您可以表示两个全局变量相互依赖的不安全情况)。另外,当动态链接模块时,它可能是不干净的ApiManager& apiMng() { static ApiManager rc; return rc; }