Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my struct destructed twice with `std::variant` and `std::monostate`?

I am trying to learn std::variant. I do not understand why in this example, where I prefer not to initialize ab yet, and I use std::monostate for that, the class A gets constructed once, but destructed twice. What is happening?

#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();
}

Running this example gives the output below.

Constructing A
Destructing A
Destructing A
like image 709
Chiel Avatar asked Sep 10 '25 16:09

Chiel


1 Answers

This line:

ab = A();

Is creating a temporary A object, and then moving it into ab.
You can observe this by adding copy/move constructors and assignment operators:

#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();
}

Output:

Constructing A
Move constructing A
Destructing A
Destructing A

You can avoid the copy/move, by using std::variant::emplace.
If you replace the above mentioned line with:

ab.emplace<A>();

The output should become:

Constructing A
Destructing A
like image 174
wohlstad Avatar answered Sep 13 '25 07:09

wohlstad