"struct atomic"的复制构造函数

Copy constructor of "struct atomic"

本文关键字:构造函数 复制 atomic struct      更新时间:2023-10-16

我有以下代码:

enum class State : uint32_t
{
    FREE,
    IDLE,
    COAST,
    MOVE,
    STOP
};
std::atomic<State> car1_state = State::IDLE;  <--- Line a
std::atomic<State> car2_state(State::IDLE);   <--- Line b

以下是原子头文件的片段:

// c++ header file - atomic
template<typename _Tp>
  struct atomic
  {
  private:
    _Tp _M_i;
  public:
    atomic() noexcept = default;
    ~atomic() noexcept = default;
    atomic(const atomic&) = delete;                <--- Line c
    atomic& operator=(const atomic&) = delete;
    atomic& operator=(const atomic&) volatile = delete;
    constexpr atomic(_Tp __i) noexcept : _M_i(__i) { }    <--- Line d
    operator _Tp() const noexcept
    { return load(); }
    operator _Tp() const volatile noexcept
    { return load(); }
    _Tp
    operator=(_Tp __i) noexcept
    { store(__i); return __i; }
....

我有几个问题:

  • b行编译良好。我在第d行中理解的构造函数被调用了。对吧
  • a行编译失败。根据错误消息,调用了行c中的复制构造函数,因此出现了错误消息"使用已删除的函数"(我理解)

有人能帮我理解为什么Linea最终会调用Linec(而不是Line1d)吗。

复制初始化需要一个可访问的、非显式的复制或移动构造函数,因为它从相同类型的临时prvalue正式初始化变量。也就是说,
Foo a = x;

相当于:

Foo a = Foo(x);

您的类型没有可访问的复制构造函数,因此出现错误。相比之下,直接初始化不需要复制构造函数:

Foo a(x);

这是直接初始化和复制初始化之间的区别。让我们概括一下:

A a1 = b;
A a2(b);

如果b的类型是A,则这两条线是相同的。它们都将调用A的复制构造函数。

然而,如果b的类型不同于A,则它们的语义也不同。a2通过直接初始化来初始化,调用A的适当构造函数,该构造函数采用b的类型。

另一方面,a1是通过复制初始化来初始化的,的作用是"从参数初始化一个临时对象,然后使用复制构造函数将该临时对象复制到最终对象中。"因此,在这种情况下,复制初始化等效于:

A a1(A(b));

在您的情况下,这将失败,因为复制构造函数已被删除,并且没有移动构造函数。

为了完全回答您的第二个问题,它不调用Linec而不是Lined,而是除了Lined之外的