静态初始化Fiasco - On Purpose

时间:2011-06-14 19:10:44

标签: c++

为了好玩,我正在调查静态对象的动态初始化顺序。 在文件名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 - a 0 - 主要

到目前为止没有问题。

现在我创建u.cpp就像a.cpp但使用“u”。重新编译/重新运行,“u”不会显示在列表中。

是因为我从未引用过你吗?我从来没有引用过a,b,c,但是我改变了主要的:

#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已经更新为包含“你”吗?我认为应该有一个更好的解释,而不是你在字母表中的后面。

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

似乎编译链接顺序很重要:

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

有趣!