所以我把这个程序给了g ++和clang(在Linux,x86_64上):
#include <iostream>
using namespace std;
template<char... Cs>
struct A {
static const string s;
static A a;
~A() {
cout << "s = " << s << "\n";
}
};
template<char... Cs>
const string A<Cs...>::s = {{Cs...}};
template<char... Cs>
A<Cs...> A<Cs...>::a;
int main(void)
{
(void)A<'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'>::a;
return 0;
}
Clang输出{{1}}(如预期的那样)。
g ++(版本5到8)输出s = aaaaaaaaaaaaaaaa
(非常意外)。
如果您不使用可变参数模板,则不会发生这种情况(如果您删除所有&lt;&gt;代码并内联字符列表以初始化s = s = aaaaaaaa
。
如果用字符数组替换A::s
(并改为使用std::string
),也不会发生这种情况。
这段代码不是故意的,还是编译器错误?
答案 0 :(得分:8)
您的代码不正确。标准的重要部分是6.6.3 / 1 [basic.start.dynamic] 在N4659:
如果变量是a,则静态存储持续时间的非局部变量的动态初始化是无序的 隐式或显式实例化的专业化[...]
因为初始化没有排序,所以不能依赖于破坏的顺序。无论施工顺序如何,任何订单都是合法的。见6.6.4 / 3 [basic.start.term]
因此,在崩溃s
之前,允许gcc销毁a
,
这是发生了什么,并导致奇怪的输出。 Live