Windows 上的 Clang/LLVM 7 和 8 多次初始化内联静态数据成员(使用 link.exe 和 lld-
Clang/LLVM 7 and 8 on Windows initialize inline static data member multiple times (with both link.exe and lld-link.exe)
Clang/LLVM 7 和 8 为每个TU 初始化一次内联静态数据成员。据我了解C++17,这是不正确的。
尽管可以在多个 TU 中定义内联变量,但编译器和/或链接器必须确保它在程序中仅存在一次,因此只初始化一次。
下面的小程序显示了Clang/LLVM会发生什么(在Visual Studio 2017和2019 RC中使用LLVM编译器工具链扩展进行了测试(:
标题.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
#include "header.h"
int main()
{
S::a.f();
}
TU2.cpp
#include "header.h"
TU3.cpp
#include "header.h"
TU4.cpp
#include "header.h"
此程序打印:
ctor 010D4020
ctor 010D4020
ctor 010D4020
ctor 010D4020
f 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020
这是 A 的唯一对象的四个初始化(实际上每个 TU 一个(,而不是一个(如 C++17 要求的那样(。
程序应打印:
ctor 010D4020
f 010D4020
dtor 010D4020
顺便说一下,这就是MSVC所做的。
这是 clang/LLVM 中的一个错误,对吧?
inline
关键字的主要功能是它以两种方式修改 ODR 规则:
-
允许多个定义(有一些限制(
-
生成的对象被"折叠"到单个实例中:
具有外部链接的内联函数或变量在所有翻译单元中应具有相同的地址。
C++17 中唯一的补充是它还允许static
数据成员声明成为定义。就是这样。
static
数据成员仍然具有相同的链接(在您的情况下是外部链接(、存储持续时间和生存期,并且出于所有实际目的,就像全局定义的变量一样工作。 参见 [class.static.data]/6:
静态数据成员的初始化和销毁与非局部变量完全相同
这基本上意味着它应该与这样工作
:struct A
{
A() { std::cout << "ctor "; }
~A() { std::cout << "dtor "; }
};
A a; // in one of the TU's
extern A a; // in all other TU's
结论:
这是叮当声中的一个错误。static
S::a
必须初始化并销毁一次。
此错误已在基于 SVN r361807 的当前快照构建中修复。
相关文章:
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 静态数据成员模板专用化的实例化点在哪里
- 调用在 HXX 文件中声明的静态数据成员
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 静态数据成员:它"const declaration / constexpr definition"起作用?
- 何时需要定义类的静态数据成员 (un/-)
- 为什么静态数据成员不能在c++11中的类中初始化
- 静态数据成员的模板专用化
- 拒绝包含某些公共静态数据成员的类型
- GCC:在调试构建中优化的静态数据成员
- 类模板静态数据成员定义/声明/初始化
- C++ 中的静态数据成员
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- 使用 lambda 函数初始化静态数据成员
- 引用静态数据成员
- 学习C++并在早期示例中遇到错误(在非静态数据成员之前需要构造函数)
- Windows 上的 Clang/LLVM 7 和 8 多次初始化内联静态数据成员(使用 link.exe 和 lld-
- 为什么不能使用"( )"为类的非静态数据成员提供默认值?
- 不带初始值设定项的 constexpr 静态数据成员