为什么我的结构被 `std::variant` 和 `std::monostate` 破坏了两次?

Chi*_*iel 25 c++ c++17 std-variant

我在尝试学习std::variant。我不明白为什么在这个例子中,我不想初始化ab,并且我std::monostate为此使用,类A被构造一次,但被破坏两次。怎么了?

#include <iostream>
#include <variant>

struct A
{
    A() { std::cout << "Constructing A\n"; }
    ~A() { std::cout << "Destructing A\n"; }
};


struct B
{
    B() { std::cout << "Constructing B\n"; }
    ~B() { std::cout << "Destructing B\n"; }
};


int main()
{
    std::variant<std::monostate, A, B> ab;
    ab = A();
}
Run Code Online (Sandbox Code Playgroud)

运行此示例会给出以下输出。

Constructing A
Destructing A
Destructing A
Run Code Online (Sandbox Code Playgroud)

woh*_*tad 38

这行:

ab = A();
Run Code Online (Sandbox Code Playgroud)

正在创建一个临时A对象,然后将其移入ab.
您可以通过添加复制/移动构造函数和赋值运算符来观察这一点:

#include <iostream>
#include <variant>

struct A
{
    A()                    { std::cout << "Constructing A\n"; }
    A(A const&)            { std::cout << "Copy constructing A\n"; }
    A(A&&)                 { std::cout << "Move constructing A\n"; }
    A& operator=(A const&) { std::cout << "Copy assigning A\n"; return *this; }
    A& operator=(A&&)      { std::cout << "Move assigning A\n"; return *this; }
    ~A()                   { std::cout << "Destructing A\n"; }
};

struct B
{
};

int main()
{
    std::variant<std::monostate, A, B> ab;
    ab = A();
}
Run Code Online (Sandbox Code Playgroud)

输出:

Constructing A
Move constructing A
Destructing A
Destructing A
Run Code Online (Sandbox Code Playgroud)

您可以通过使用来避免复制/移动std::variant::emplace
如果将上述行替换为:

ab.emplace<A>();
Run Code Online (Sandbox Code Playgroud)

输出应变为:

Constructing A
Destructing A
Run Code Online (Sandbox Code Playgroud)


小智 15

我在你的代码中添加了 2 行。

struct A
{
    A() { std::cout << "Constructing A\n"; }
    A(const A& a) { std::cout << "Copy  constructing A\n"; }  // <== here
    ~A() { std::cout << "Destructing A\n"; }
};


struct B
{
    B() { std::cout << "Constructing B\n"; }
    B(const B& a) { std::cout << "Copy  constructing B\n"; }   // <== and here
    ~B() { std::cout << "Destructing B\n"; }
};
Run Code Online (Sandbox Code Playgroud)

那么我们可以得到这样的结果:

Constructing A
Copy  constructing A
Destructing A
Destructing A
Run Code Online (Sandbox Code Playgroud)

我对 std::variant 不熟悉,我只是希望上面的实验能让你更接近真正的答案。:)