Search code examples
c++c++17std-variant

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

Solution

  • 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