当前位置:  开发笔记 > 编程语言 > 正文

Windows上的Clang/LLVM 7.0.1多次初始化内联静态数据成员

如何解决《Windows上的Clang/LLVM7.0.1多次初始化内联静态数据成员》经验,为你挑选了1个好方法。

Windows上的Clang/LLVM 7.0.1 每个TU初始化一次内联静态数据成员.据我所知,C++ 17这是不正确的.

尽管可以在多个TU中定义内联变量,但编译器和/或链接器必须确保它在程序中仅存在一次,因此仅初始化一次.就像多重定义的内联函数一样,在程序中只存在一次.请参阅以下小程序:

// header.h

#include 

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中的一个错误,对吧?



1> rustyx..:

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

结论:

这是Clang中的错误。在static S::a必须进行初始化和销毁一次。

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有