代码之家  ›  专栏  ›  技术社区  ›  MikeMB

列表初始化是否将原子初始化为零?

  •  4
  • MikeMB  · 技术社区  · 7 年前

    问题:

    std::atomic<int> a{}; 初始化 a (归零)还是不归零?

    背景:

    通常,我希望 T a{}; 要么给出编译时错误,要么确保 已初始化并准备好使用。不是因为 T 是一个基本的/POD类型,关于aggregate/zero/value/list初始化的语言规则导致所有内容都被初始化为零(我不知道确切是什么),或者因为调用了默认构造函数,它“通常”将对象带入可用状态。 当然,需要(不只是允许)双初始化的类存在,但似乎很少见——特别是在标准库中。

    但是,对于 std::atomic

    1)默认的构造函数很简单:除了静态和线程本地对象的零初始化之外,不会进行任何初始化。std::atomic_init可用于完成初始化。

    [...]

    默认的初始化std::atomic不包含T对象,其唯一有效的用途是std::atomic_init的销毁和初始化,请参见 LWG 2334

    我读到这个

    std::atomic<int> a{};
    assert(a.load() == 0);
    

    不仅仅是不确定的行为,实际上是不确定的行为。

    如果是这样的话,那么原子的使用将是一个巨大的陷阱,特别是因为它似乎是在大多数平台上“按预期”工作的UB案例之一: https://godbolt.org/g/DmEGDE

    编辑: 我也不太明白,为什么这个“确保与C兼容”只保证所有位都设置为零会有什么危害?

    注: 我知道我可以写 std::atomic<int> a{0}

    1 回复  |  直到 7 年前
        1
  •  1
  •   YSC    7 年前

    对, std::atomic<int> a{}; 初始化 a 归零。

    此语法开始于 值初始化 属于 std::atomic<int> ,依次运行零初始化 . 这意味着,即使 标准::原子<int> 具有默认构造函数 ,它不是 以及 初始化为零。


    (一)

    [dcl.init]/8.2

    8)初始化类型为 T 指:

    8.2)如果 T型 是(可能是cv限定的)类类型,没有用户提供或删除的默认构造函数,则对象初始化为零,并检查默认初始化的语义约束,如果 T型 有一个非平凡的默认构造函数,对象是默认初始化的;

    2个)

    [atomics.types.operations]/2

     atomic() noexcept = default;
    

    效果:使原子对象处于未初始化状态。[注:这些语义确保与C.end Note兼容]

    三)

    [dcl.fct.def.default]/5

    如果函数是用户声明的,并且在第一次声明时未显式默认或删除,则该函数是用户提供的。