题
我可以控制静态对象被破坏的顺序? 有什么办法来强制执行我所希望的顺序?例如,以指定在某些方面,我想一定对象被销毁最后,或至少又一个静态对象?
解决方案
在静态对象破坏施工相反的顺序进行。和施工顺序是非常难以控制。你可以肯定的唯一的事情是,在同一个编译单元定义了两个对象将在定义的顺序来构建。别的是或多或少随机的。
其他提示
其他答案,这样坚持,它不能做。他们是对的,依据规范 - 但有是的一招,可以让你做到这一点。
创建一个唯一的单的静态变量,它包含了所有其他的事情,你通常会做静态变量,类或结构的,像这样:
class StaticVariables {
public:
StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { };
~StaticVariables();
Var1Type *pvar1;
Var2Type *pvar2;
};
static StaticVariables svars;
您可以创建你需要的任何顺序变量,更重要的是,在任何你需要的才能,在构造函数和析构函数StaticVariables
摧毁的他们。为了使这个完全透明的,您可以创建一个变量静态引用过,像这样:
static Var1Type &var1(*svars.var1);
瞧 - 总控制。 :-)这就是说,这是额外的工作,一般是不必要的。但是,当它的是的必要,这是非常有用的了解它。
短的答案:一般情况下,无
稍长回答:对于在单个翻译单元全球静态对象的初始化顺序是从上到下,破坏顺序正好相反。几个翻译单元之间的顺序是不确定的。
如果你真的需要一个特定的顺序,你需要做这件事你自己。
静态对象被销毁在它们正在构造(例如,第一构造的对象被销毁最后)的顺序相反,也可以通过使用所描述的技术控制,其中静态对象构成的序列,项目47,在迈尔斯的书 “的确保全局对象,他们已经习惯前初始化” 的有效C ++ 的。
例如,以指定在某些方面,我想一定对象被销毁最后,或至少又一个静态onject?
确保它的其他静态对象之前建造。
如何控制施工顺序?不是所有的静力学的是在相同的DLL。
我将忽略(为简单起见)的事实,他们不是在相同的DLL。
我迈尔斯项目47(其为4页长)的复述如下。假设你全球在这样的头文件中被定义...
//GlobalA.h
extern GlobalA globalA; //declare a global
...添加一些代码,其包括这样的文件...
//GlobalA.h
extern GlobalA globalA; //declare a global
class InitA
{
static int refCount;
public:
InitA();
~InitA();
};
static InitA initA;
这样的效果将是包括GlobalA.h任何文件(例如,用于定义第二个全局变量的GlobalB.cpp源文件)将定义INITA类,这将任何内容之前被构造的一个静态实例否则在该源文件(例如之前的第二全局变量)。
此INITA类有一个静态的基准计数器。当第一INITA实例构造,这是目前保证是你GlobalB实例之前构造,该构造INITA可以做任何事必须做,以确保globalA初始化实例。
世界上没有办法做到这一点的C ++标准,但如果你有特定的编译器的一个良好的工作知识内部构件大概可以实现的。
在Visual C ++中的指针的静态初始化函数位于.CRT$XI
段(对于C类型的静态初始化)或.CRT$XC
段(用于C ++类型的静态初始化)链接器收集的所有声明和字母顺序将它们合并。其中通过使用在适当片段声明你对象时出现的静态初始化,可以控制的顺序
#pragma init_seg
例如,如果你想文件A的物体被之前文件B的创建:
文件A.cpp:
#pragma init_seg(".CRT$XCB")
class A{}A;
文件B.cpp:
#pragma init_seg(".CRT$XCC")
class B{}B;
.CRT$XCB
被.CRT$XCC
之前合并英寸当通过静态初始化函数指针CRT迭代时,它将遇到文件的文件B之前。
在WATCOM该段是XI和变化的#pragma初始化可以控制结构:
#pragma initialize before library
#pragma initialize after library
#pragma initialize before user
...看到更多的文档
没有,你不能。你永远不应该依赖于其他建筑/销毁静态对象的。
您可以随时使用一个单控制建设/破坏你的全球资源的顺序。
你真的需要的变量main
之前被初始化?
如果你没有,你可以使用一个简单的成语实际控制建设和破坏轻松的顺序,在这里看到:
#include <cassert>
class single {
static single* instance;
public:
static single& get_instance() {
assert(instance != 0);
return *instance;
}
single()
// : normal constructor here
{
assert(instance == 0);
instance = this;
}
~single() {
// normal destructor here
instance = 0;
}
};
single* single::instance = 0;
int real_main(int argc, char** argv) {
//real program here...
//everywhere you need
single::get_instance();
return 0;
}
int main(int argc, char** argv) {
single a;
// other classes made with the same pattern
// since they are auto variables the order of construction
// and destruction is well defined.
return real_main(argc, argv);
}
它不会停止你真正尝试创建类的第二个实例,但如果你做的断言将失败。根据我的经验,它工作正常。
可以有效地通过具有static std::optional<T>
代替T
实现类似的功能。只是初始化它,你会用一个变量做,用间接使用,并通过分配std::nullopt
(或升压,boost::none
)摧毁它。
这是从具有它已经预分配内存的指针,这是我想你想要的东西不同。因此,如果你破坏它与(或许更晚)重新创建它,你的对象将具有相同地址(你可以保留),你不当时付出的动态分配/释放的费用。
使用boost::optional<T>
如果你没有std::
/ std::experimental::
。