在我的程序中,我有一堆类在程序执行期间只会创建一个实例。它们在初始化时只创建一次,在关闭时只销毁一次。
这些类都倾向于提供程序的许多不同部分使用的非常广泛的功能,因此将它们作为全局外部非常干净且易于理解,而不是将它们封装在另一个类中或传递指针。
该程序是多线程的,所有这些类都包含自己的互斥锁以供访问。
这种方法有什么问题吗?如果是这样,推荐的替代方案是什么。
在我的程序中,我有一堆类在程序执行期间只会创建一个实例。它们在初始化时只创建一次,在关闭时只销毁一次。
这些类都倾向于提供程序的许多不同部分使用的非常广泛的功能,因此将它们作为全局外部非常干净且易于理解,而不是将它们封装在另一个类中或传递指针。
该程序是多线程的,所有这些类都包含自己的互斥锁以供访问。
这种方法有什么问题吗?如果是这样,推荐的替代方案是什么。
使用单例模式,如下所示:
Foo& foo() { static Foo x; return x; }
这是完全线程安全的。请参见此处:G++ 4.6 -std=gnu++0x:静态局部变量构造函数调用时序和线程安全
它是由当前标准保证的。
此外,这优于静态初始化的全局变量,因为如果您有多个上述变量,它们将以正确的依赖顺序懒惰地初始化。
Foo& foo() { static Foo x; return x; }
Bar& bar() { static Bar x; return x; }
并且在 Bar::Bar 中调用了 foo(),那么 Foo 单例将在 Bar 之前创建。
如果我有使用过的全局变量:
// Foo.cpp
Foo foo;
// Bar.cpp
Bar bar;
不保证此类订购。
...变量的初始化相对于在不同翻译单元中定义的变量的初始化是不确定的。
您可以使用单例,但要确保线程安全。有关教程,请查看单例模式 - 1. 线程安全
一个例子是
static SomeSingleton* getInstance()
{
lock_mutex();
if(!pInstance_)
pInstance_ = new SomeSingleton();
unlock_mutex();
return pInstance_;
}
通过在类中使用全局变量,会使它们难以测试。他们的行为现在取决于一个全球状态,这使得对他们进行推理变得困难。一类取决于全局变量。另一个类也依赖于它。两者都可以随时更改全局变量的状态。本质上,您在两个类之间创建了相互依赖关系。每次访问全局变量时,您都离依赖地狱的一个版本更近了一步。
您已经提到您不想将它们作为指针传递。其实我更喜欢这种方法。通过将依赖项(您的全局变量)显式传递给方法或构造函数,您可以告诉全世界。如果您需要将十个依赖项传递给您的方法,您可能需要重新考虑您的解决方案。这可能需要大量工作,但有助于改进程序的体系结构。
你已经写到你的类“倾向于呈现非常广泛的功能”。这可能表明它们应该被分解成更小的组件,以便您只需要传递您实际需要的功能。
我的建议是
c++在调用全局对象构造函数的顺序上有很大的问题有人称之为“全局初始化惨败”它与多线程无关,但与初始化有关如果你的程序有很多全局对象,那么它可能会导致一些问题(当然有一些方法可以解决这个问题)
您可以使用模式“单例”,但我不确定它是否对您有用