有关初始化非本地静态的规则是什么?

时间:2012-12-05 02:02:17

标签: c++ c++11

假设我有一个类,其唯一目的是在构造对象时产生的副作用(例如,使用工厂注册类):

class SideEffectCauser {
public:
  SideEffectCauser() { /* code causing side-effects */ }
};

另外假设我想让一个对象为每个翻译单元创建一次这样的副作用。对于每个这样的翻译单元,我希望能够在.cpp文件中的命名空间范围内放置一个SideEffectCauser对象,例如,

SideEffectCauser dummyGlobal;

但是C ++ 03标准的3.6.2 / 3建议除非使用.cpp文件中的对象或函数,以及this和在线等文章,否则不需要构造此对象诸如this之类的讨论表明这些对象有时不会被初始化。

另一方面,Is there a way to instantiate objects from a string holding their class name? 有一个声称可行的解决方案,我注意到它基于使用像SideEffectCauser这样的类型的对象作为静态数据成员,而不是全球,例如,

class Holder {
  static SideEffectHolder dummyInClass;
};

SideEffectHolder Holder::dummyInClass;

dummyGlobaldummyInClass都是非本地静态,但仔细研究C ++ 03标准的3.6.2 / 3表明该段落仅适用于命名空间范围内的对象。我实际上无法在C ++ 03标准中找到任何内容,即当类范围内的非局部静态动态被动态初始化时,尽管9.4.2 / 7表明相同的规则适用于它们在命名空间中的非局部静态范围。

问题1:在C ++ 03中,有没有理由相信dummyInClassdummyGlobal更有可能被初始化?如果没有使用同一翻译单元中的任何功能或对象,或者两者都可以未初始化?

问题2:C ++ 11中有什么变化吗? 3.6.2和9.4.2中的措辞与C ++ 03版本不同,但据我所知,上面描述的场景没有规定行为差异。

问题3:是否有可靠的方法在函数体外部使用类SideEffectHolder之类的对象来强制发生副作用?

2 个答案:

答案 0 :(得分:1)

我认为唯一可靠的解决方案是为特定的编译器和运行时设计它。没有标准涵盖共享库中全局变量的初始化,我认为这是最复杂的情​​况,因为这很大程度上取决于加载器,因此依赖于操作系统。

Q1:不 Q2:没有任何实际意义 问题3:不是标准的方式

答案 1 :(得分:0)

我在Linux下使用与g ++ / C ++ 11类似的东西,并按预期注册我的工厂。我不确定为什么你不会得到调用的函数。如果要实现所描述的内容,则意味着该单元中的每个函数都必须调用初始化函数。我不太清楚如何做到这一点。我的工厂也位于命名空间内,尽管它名为命名空间。但我不明白为什么不会被召唤。

namespace snap {
namespace plugin_name {
class plugin_name_factory {
public:
  plugin_name_factory() { plugin_register(this, name); }
...
} g_plugin_name_factory;
}
}

请注意,无论如何都不应该在C ++中使用static关键字。静态定义通常比全局定义慢。