【问题标题】:Static Initialization Fiasco - On Purpose静态初始化惨败 - 故意
【发布时间】:2011-06-14 19:10:44
【问题描述】:

只是为了好玩,我正在研究静态对象的动态初始化顺序。 在文件名 t.h 中,我放了

struct T {
   static std::vector<std::string> me;
   static int add(std::string s) { me.push_back(s); return me.size(); }
};

(加上向量和字符串所需的标题。) “std::vector T::me”在 t.cpp 中。 文件 main.cpp 打印出 T::me: 中的值:

#include "t.h"
#include <iostream>
using namespace std;

int main()
{
    T::me.push_back("main");
    cout << "T::me.size()=" << T::me.size() << endl;
    for (unsigned i = 0; i<T::me.size(); ++i) {
        cout << i << "-" << T::me[i] << endl;
    }
    return 0;
}

接下来,我创建“a.cpp”并将以下内容放入其中:

#include "t.h"

int a = T::add("a");

根据需要使用“b”和“c”对文件 b.cpp 和 c.cpp 执行类似操作。 使用 g++ *.cpp 编译,然后运行 ​​./a.out。未指定从编译单元到编译单元的静态初始化顺序。就我而言,它始终按字母倒序排列。我得到: 3 - c 2 - b 1 - 一个 0 - 主要

目前没有问题。

现在我像 a.cpp 一样创建 u.cpp,但使用“u”。重新编译/重新运行,“u”没有出现在列表中。

是因为我从来没有引用过你吗?我从未引用过 a、b、c,但我更改了 main:

#include "t.h"
#include <iostream>
using namespace std;

extern int u;

int main()
{
    cout << "u=" << u << endl;
    T::me.push_back("main");
    cout << "T::me.size()=" << T::me.size() << endl;
    for (unsigned i = 0; i<T::me.size(); ++i) {
        cout << i << "-" << T::me[i] << endl;
    }
    return 0;
}

程序打印出“u=2”,但“u”不在列表中。你不应该在使用之前被动态初始化,因此,T::me 已经更新为包含“u”吗?我认为应该有比字母表中 u 排在 t 之后更好的解释。

【问题讨论】:

  • 需要我指出,试图找出官方未指明的行为的细节只是远离依赖这些细节的一步,我们作为一个社区不希望任何一个?
  • “只是为了好玩”是一个合理的借口。我愿意让 OP 怀疑他们不会发送任何依赖于这种行为的生产代码,无论它可能被发现是什么。但是按照这个逻辑,也许应该把它移到programmers.stackexchange.com
  • 我不认为我的问题属于未指定行为的领域。如果我问“你什么时候初始化 w.r.t. a,b,c...”将是未指定的。

标签: c++


【解决方案1】:

我明白了。很简单,真的。 T::me 根据 C++ 的规则静态初始化为零。但是,有一个构造函数可以动态运行。无法保证该构造函数何时运行。显然 - 在这种情况下 - 在 u 初始化之后运行。

【讨论】:

    【解决方案2】:

    看来编译的链接顺序很重要:

    g++ -o m a.cpp u.cpp t.cpp main.cpp
    

    给予

    a=2
    u=1
    T::me.size()=3
    0-u
    1-a
    2-main
    

    但是

    g++ -o m main.cpp t.cpp a.cpp u.cpp
    

    给予

    a=2
    u=1
    T::me.size()=1
    0-main
    

    在最后一种情况下反转a.cppu.cpp 会导致a=1u=2

    有趣!

    【讨论】:

    • 其实就是链接的顺序:用g++ -c编译各个模块,然后用g++按照不同的顺序链接。
    猜你喜欢
    • 2011-07-15
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    相关资源
    最近更新 更多