在Windows环境下,Clang/LLVM 7和8对inline静态数据成员进行了一次TU初始化。就我理解的C++17而言,这是不正确的。
虽然inline变量可以在多个TU中定义,但编译器和/或链接器必须确保它在程序中只存在一次,因此仅被初始化一次。
以下小程序展示了Clang/LLVM的具体操作(在Visual Studio 2017和2019 RC中测试了LLVM Compiler Toolchain扩展):
// header.h
#include <iostream>
struct A
{
A() { std::cout << "ctor " << this << std::endl; }
~A() { std::cout << "dtor " << this << std::endl; }
void f() { std::cout << "f " << this << std::endl; }
};
struct S
{
inline static A a; // C++17 inline variable, thus also a definition
};
// TU1.cpp
->// TU1.cpp
#include "header.h"
int main()
{
S::a.f();
}
// TU2.cpp
#include "header.h"
#include "header.h"
// TU4.cpp
// TU4.cpp 是一个代码文件的文件名。#include "header.h"
这个程序会输出:
ctor 010D4020
ctor 010D4020
ctor 010D4020
ctor 010D4020
f 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020
这意味着A类的唯一对象将有四个初始化(实际上是每个翻译单元一个),而不是像C++17要求的仅有一个。
程序应该输出:
ctor 010D4020
f 010D4020
dtor 010D4020
顺便说一下,这就是MSVC的作用。
这是clang/LLVM中的一个bug,对吧?