提问者:小点点

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


我正在尝试学习标准::变体。我不明白为什么在这个例子中,我不想初始化 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

共2个答案

匿名用户

此行:

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 assignment A\n"; return *this; }
    A& operator=(A&&)      { std::cout << "Move assignment 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

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

ab.emplace<A>();

输出应变为:

Constructing A
Destructing A

匿名用户

我在你的代码中添加了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"; }
};

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

Constructing A
Copy  constructing A
Destructing A
Destructing A

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