3

在文件 maybe_use_foo.cpp 中:

namespace {
    class Foo { /* ... */ };
    Foo* const the_foo = new Foo;
}

void funtion_callable_from_another_tu_during_process_wide_initialization() {
    // If we haven't yet run static initialization for this TU,
    // but some other static initializer called us, ignore the request.
    if (!the_foo)
      return;

    // OK, static initializers for this TU have run, foo exists, use it.
    the_foo->doSomething();
}

那么,无论上述是否可取,它总是有效吗?在我看来,它假设在 TU 的静态初始化运行之前静态初始化为零。C++ 标准(C++03?C++11?)能保证吗?

提出问题的另一种方法是询问当解释为 Foo* 时,哪些值序列保存在“the_foo”的存储中。肯定是{NULL/nullptr, new Foo},还是{undefined, new Foo},或者别的什么?

请不要建议其他组织方式:我不是在寻找如何更好地做到这一点的建议,我在寻找对技术合法性的更深入了解。

4

3 回答 3

4

C++11

[basic.start.init]/2

具有静态存储持续时间 (3.7.1) 或线程存储持续时间 (3.7.2) 的变量应在任何其他初始化发生之前进行零初始化 (8.5)。

[...]

零初始化和常量初始化一起称为静态初始化;所有其他初始化都是动态初始化。静态初始化应在任何动态初始化发生之前执行。

也就是说,是的,变量是零初始化的,但不,它们在静态初始化之前不是零初始化的(但作为静态初始化的一部分)。


OP 中的函数只会在动态初始化期间被调用,因为它不会在零初始化期间被调用,并且必须是一个constexpr函数才能成为常量初始化的一部分。

于 2013-10-29T12:51:19.620 回答
4

是的,C++03 标准在 [basic.start.init] 中解释:

具有静态存储持续时间(3.7.1)的对象应在任何其他初始化发生之前进行零初始化(8.5)。

8.5.1 解释:

对 T 类型的对象进行零初始化意味着:

— 如果 T 是标量类型(3.9),则将对象设置为转换为 T 的值 0(零);

[..]

于 2013-10-29T12:51:26.967 回答
0

您的代码可能会导致错误。链接器通常不会尝试深入理解单独模块中的初始化部分。尽量通过静态函数提供变量,例如

namespace {
    Foo* the_foo() {
        static Foo* g_ = new Foo;
        return g_;
    }
}
于 2013-10-29T12:55:55.467 回答