编译器是否具有生成所有全局变量的依赖关系树所需的所有信息,并为它们创建定义良好且正确的初始化顺序?我意识到你可以用全局变量写一个循环依赖 - 只使 案例未定义的行为 - 并且编译器可以警告并且可能有关它的错误。
通常,这种情况的原因是它会给编译器制造商带来负担,或导致编译速度显着降低。我没有任何指标或证据表明在这种情况下这些都不是真的,但我倾向于两者都不是真的。
答案 0 :(得分:5)
嗯,想象下面的设置,这是完全有效的C ++,但分析很棘手:
// TU #1
bool c = coin();
// TU #2
extern bool c;
extern int b;
int a = c ? b : 10;
// TU #3
extern bool c;
extern int a;
int b = c ? 20 : a;
很明显,TU#1需要先进行初始化,然后呢?带有参考静态的标准解决方案允许您使用标准C ++正确编写此代码,但通过修复全局初始化顺序来解决此问题似乎很棘手。
答案 1 :(得分:3)
编译器可以处理的部分实际上是定义:具有静态存储持续时间的对象按其定义出现在翻译单元中的顺序构造。销毁订单正好相反。
在翻译单元之间对对象进行排序时,通常不会显式表示对象的依赖关系组。但是,即使依赖项被明确地重新创建,它们实际上也没有多大帮助:在小型项目上,可以相对容易地管理具有静态存储持续时间的对象之间的依赖关系。事情变得有趣的是大型对象,但这些对象的初始化的可能性要高得多。
static T global = functionWhichMayuseTheword();
,即在订购有用的情况下,它一定不起作用。
有一种简单的方法可以确保及时构造对象,这在C ++中甚至是线程安全的(在C ++ 03中它不是线程安全的,因为这个标准没有提到任何线程的概念。第一个位置):使用函数本地static
对象并返回对它的引用。对象将根据需要构建,但如果它们之间存在依赖关系,则通常可接受:
static T& global() {
static rc = someInitialization();
return rc;
}
鉴于有一个简单的解决方法,提案或工作实现都没有证明提案确实有效,因此没有兴趣改变全局对象初始化的状态。更不用说改进对全局对象的支持似乎比使goto
更好。
答案 2 :(得分:2)
我不是编译器的作者,所以我带着我的话说。我认为原因如下。
1)希望保留单独编译的C模型。肯定允许链接时间分析,但我怀疑他们不想要它。
2)Meyers Singleton(特别是现在已经成为线程安全的)提供了一个足够好的选择,因为它几乎像全局变量一样易于使用,但提供了您正在寻找的保证。