文件范围的原子是否受初始化顺序惨败的影响?

acm*_*acm 10 c++ static initialization undefined-behavior c++11

请考虑以下内容,其中我们在不同的转换单元中有两个文件范围的对象,这是通过初始化顺序fiasco的未定义行为的常规设置:

a.hpp:

struct thing {
public:
    thing(int value);
    ~thing();

    int value() const;

    static int count();

private:
    int _value;
};
Run Code Online (Sandbox Code Playgroud)

a.cpp:

#include "a.hpp"

#include <atomic>

namespace {
    std::atomic<int> things;
}

thing::thing(int value) : _value(value) {
    ++things;
}

thing::~thing() {
    --things;
}

int thing::value() const {
    return _value;
}

int thing::count() {
    return things.load();
}
Run Code Online (Sandbox Code Playgroud)

b.cpp:

#include <iostream>

#include "a.hpp"

namespace {
    thing static_thing(42);
}

void foo() {
    std::cout << static_thing.value() << ' ' << thing::count() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

这是代码受制于文件之间的初始化顺序的悲剧范围的原子thingsa.cpp和文件作用域static_thingb.cpp?如果没有,为什么不呢?特别是,std :: atomic有什么特别的东西可以删除原本清楚的init命令惨败?是否有一个特定的概念可以命名为使用静态断言强制执行此操作?就像是:

static_assert(std::is_trivial<decltype(things)>::value, "file static counter is not trivial");
Run Code Online (Sandbox Code Playgroud)

如果没有std::is_trivial,是否有另一个概念和相关的类型特征更好地模拟这个?

相反,是否存在去初始化惨败?同样的问题,如果是,为什么,或为什么不.

Joh*_*ger 1

我对 C++“初始化顺序惨败”的理解是,它仅适用于需要在运行时调用构造函数的情况。如果代码可以将内存位置初始化为固定值,则该值会.data像其他预初始化 POD(普通 Ol' 数据)一样被放入“初始化数据”链接器部分 ( ) 中,并且有没有惨败。

我建议 anatomic满足这个标准。