因此,我将此程序提供给了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输出s = aaaaaaaaaaaaaaaa
(按预期)。
g ++(版本5到8)输出s = s = aaaaaaaa
(非常意外)。
如果您不使用可变参数模板,则不会发生这种情况(如果删除所有<>代码并内联字符列表以进行初始化,则不会发生这种情况A::s
。
如果您将其替换std::string
为字符数组(并A<Cs...>::s = {Cs...}
改为使用),也不会发生这种情况。
这段代码不是本意,还是编译器错误?
您的代码不正确。该标准的重要部分是N4659中的6.6.3 / 1 [basic.start.dynamic]:
如果变量是隐式或显式实例化的专业化,则非静态变量具有静态存储持续时间的动态初始化是无序的[...]
因为初始化没有顺序,所以您不能依赖销毁顺序。任何命令都是合法的,无论构造顺序如何。参见6.6.4 / 3 [basic.start.term]
因此,允许gcc在销毁s
之前销毁它a
,这是发生的并导致奇怪的输出。现场直播。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句