c++ 为什么我的结构被'std::variant'和'std::monostate'析构了两次?

wfauudbj  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(168)

我正在学习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();
}

运行此示例将得到以下输出。

Constructing A
Destructing A
Destructing A
xlpyo6sf

xlpyo6sf1#

此行:

ab = A();

正在创建一个临时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();
}

输出:

Constructing A
Move constructing A
Destructing A
Destructing A

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

ab.emplace<A>();

输出应变为:

Constructing A
Destructing A
oalqel3c

oalqel3c2#

我在你的代码里加了两行。

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"; }
};

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

Constructing A
Copy  constructing A
Destructing A
Destructing A

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

相关问题