C++11/17 中 std::atomic 的间接和直接初始化。有什么区别?

Ami*_*mit 6 c++ std c++11 stdatomic c++17

当我看到这个 CPP Con 2017 网络研讨会时,Fedor Pikus 说:“它必须是直接初始化”

在此输入图像描述 这是网络研讨会的链接。

这些初始化方法有什么区别?(随后,为什么它必须是“直接”初始化?为什么“间接”初始化是“不是”?)

// C++17 Compiler

#include <atomic>

class Example
{
    std::atomic<bool> m_b1 = false; // 1-h
    std::atomic<bool> m_b2{ false }; // 2-h

    static void doSomethng()
    {
        std::atomic<bool> b1 = false; // 1-f
        std::atomic<bool> b2{ false }; // 2-f
        std::atomic<bool> b3(false); // 3-f

        // Do something
    }
};
Run Code Online (Sandbox Code Playgroud)

use*_*522 7

std::atomic不可复制或移动。

在 C++17 之前,复制初始化std::atomic<int> x = 0;将首先构造一个临时std::atomic<int>对象0,然后从该临时对象直接初始化x。如果没有移动或复制构造函数,这将失败,因此该行无法编译。

std::atomic<int> x(0);然而,它是直接初始化,并且仅使用构造函数的x参数进行构造。0

自 C++17 以来,没有临时的,在任何情况下x都将直接由构造函数调用0作为参数进行初始化,因此不存在std::atomic不可移动的问题。从这个意义上说,这张幻灯片现在已经过时了。

尽管在这种情况下复制初始化和直接初始化的行为现在是相同的,但总的来说两者之间仍然存在差异。特别是直接初始化选择构造函数通过重载决议直接初始化变量,而复制初始化尝试找到隐式转换序列(可能通过具有不同重载决议规则的转换构造函数或转换函数)。此外,与直接初始化相比,复制初始化不考虑标记为 的构造函数explicit

关于问题中的代码片段。1-h并且1-f是如上所述的复制初始化。3-f是上面的直接初始化。2-h2-f是直接列表初始化,在某些情况下其行为与其他两者不同,但在这里它与带括号的直接初始化具有相同的效果。

一般来说,解释初始化形式之间的所有差异需要一段时间。众所周知,这是 C++ 最复杂的部分之一。

  • @Amit不,第一种方法仍然是复制初始化,第二种方法是直接初始化。只是复制初始化的含义发生了变化。由于一些原因,这两种方法仍然不同。 (2认同)