为了好玩,我正在调查静态对象的动态初始化顺序。 在文件名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已经更新为包含“你”吗?我认为应该有一个更好的解释,而不是你在字母表中的后面。
答案 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.cpp
和u.cpp
会导致a=1
和u=2
。
有趣!