gcc 是否对静态成员初始化时间有任何保证,尤其是关于模板类?
我想知道当跨多个编译单元实例化类时,我是否可以获得静态成员(PWrap_T<T>::p_s
)将在之前初始化的硬性保证。main()
在 main 开始时尝试从每个编译单元手动触摸一个符号是不切实际的,但我不清楚其他任何东西都可以工作。
我已经用bar()
不同单位的方法进行了测试,并且总是得到想要的结果,但我需要知道 gcc 何时/是否会拉出地毯以及它是否可以预防。
此外,是否会在库完成加载之前初始化 DSO 中的所有静态成员?
#include <iostream>
#include <deque>
struct P;
inline std::deque<P *> &ps() { static std::deque<P *> d; return d; }
void dump();
struct P {
P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
void doStuff() { std::cout << id_ << " (" << inf_ << ")" << std::endl; }
int const id_;
char const *const inf_;
};
template <class T>
struct PWrap_T { static P p_s; };
// *** Can I guarantee this is done before main()? ***
template <class T>
P PWrap_T<T>::p_s(T::id(), T::desc());
#define PP(ID, DESC, NAME) /* semicolon must follow! */ \
struct ppdef_##NAME { \
constexpr static int id() { return ID; } \
constexpr static char const *desc() { return DESC; } \
}; \
PWrap_T<ppdef_##NAME> const NAME
// In a compilation unit apart from the template/macro header.
void dump() {
std::cout << "[";
for (P *pp : ps()) { std::cout << " " << pp->id_ << ":" << pp->inf_; }
std::cout << " ]" << std::endl;
}
// In some compilation unit.
void bar(int cnt) {
for (int i = 0; i < cnt; ++i) {
PP(2, "description", pp);
pp.p_s.doStuff();
}
}
int main() {
dump();
PP(3, "another", pp2);
bar(5);
pp2.p_s.doStuff();
}
(C++11 §3.6.2/4 - [basic.start.init]:)
具有静态存储持续时间的非局部变量的动态初始化是否在 main 的第一条语句之前完成是实现定义的。如果初始化推迟到 main 的第一个语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr-use (3.2) 之前。
...具有静态存储持续时间的非局部变量具有初始化副作用,即使它没有被 odr 使用(3.2、3.7.1),也必须初始化。
此外,尝试__attribute__ ((init_priority(int)))
或__attribute__ ((constructor))
为模板成员的初始化 yield warning: attributes after parenthesized initializer ignored
,我不知道有关静态初始化的其他技巧。
提前感谢任何可以给我答案的人!