我有一个类似于Local static/thread_local variables of inline functions?
的问题标准是否保证返回值始终为1,这意味着static int x
在翻译单元之间是相同的?
// TU1
template <int X>
struct C {
static int* f() { static int x = X; return &x; }
};
extern int* a1;
extern int* a2;
void sa() { a1 = C<1>::f(); a2 = C<2>::f(); }
// TU2
template <int X>
struct C {
static int* f() { static int x = X; return &x; }
};
extern int* b1;
extern int* b2;
void sb() { b1 = C<1>::f(); b2 = C<2>::f(); }
// TU3
int *a1, *a2, *b1, *b2;
void sa();
void sb();
int main() { sa(); sb(); return a1 == b1 && a2 == b2; }
答案 0 :(得分:1)
标准是否保证返回值始终为1,这意味着
static int x
在翻译单元之间是相同的?
标准需要。
同一内联函数的所有定义(可能是隐式内联)中的局部于函数的静态对象都引用一个翻译单元中定义的同一对象。
编译器会在每个翻译单元中生成该函数局部静态变量的副本,然后链接程序会选择一个副本并丢弃重复的副本。涉及共享库时,它们可能具有对象的自己的副本,但是运行时链接程序(ld.so
)会将所有引用解析为最先发现的引用。此方法称为vague linkage:
内联函数中使用的局部静态变量和字符串常量也被认为具有模糊的链接,因为它们必须在该函数的所有内联和脱机实例之间共享。
答案 1 :(得分:1)
在您的示例中,确实如此。我们需要检查[basic.def.odr] ¶6
[..]类模板可以有多个定义, 非静态函数模板,类模板的静态数据成员, 类模板的成员函数,或用于 未指定哪些模板参数([temp.spec], [temp.class.spec]),只要出现每个定义 在不同的翻译单元中,并且提供的定义满足 以下要求。给定这样一个在D中定义的名为D的实体 一个以上的翻译单元,然后
- D的每个定义应包含相同的令牌序列;和[...]
如果D是模板并且在多个翻译单元中定义, 那么前述要求应同时适用于来自 模板定义中使用的模板的封闭范围 ([temp.nondep]),以及指向 实例化([temp.dep])。如果D的定义满足所有这些条件 需求,那么行为就好像只有一个 D的定义。如果D的定义不满足这些要求 要求,那么行为是不确定的。
在这方面,您的模板还可以,就好像它们是从同一标头中包含的一样。该子句中还需要保留其他项目符号,但它们与您的示例无关。
现在,由于好像程序中模板及其成员只有一个定义,所以静态变量在两个TU中都相同变量。