static unique_ptr calls destructor twice

Viewed 9319

I use a singleton pattern which returns a reference to unique_ptr dereference. Here is the code,

#include <iostream>
#include <memory>
using std::cout; using std::endl;
using std::unique_ptr;

namespace Settings {
    class Lazy {
        Lazy() { cout << "Lazy::Lazy() " << this << endl; }
    public:
        ~Lazy() { cout << "Lazy::~Lazy() " << this << endl; }
        static Lazy &instance()
        {
            static unique_ptr<Lazy> lazy(new Lazy);
            return *lazy;
        }
    };

    Lazy &lazy()
    { return Lazy::instance(); }
}

int main()
{
    cout << "main starts!" << endl;
    auto state = Settings::lazy();
    cout << "auto state = Settings::lazy() " << &state << endl;

    cout << "main ends!" << endl;
    return 0;
}

I was expecting that the destructor of the class would call only once but although the constructor called once destructor called twice, here is the output,

main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20

why destructor called twice? And even the second call this address is different.

3 Answers

Rakete1111 solution is correct, but you might also want to delete the copy constructor and copy assignment for your singleton. That way you would prevent errors like this from ever happening.

Singleton class must disable any copy/move constructors & assignment/move operators. Otherwise this is not a singleton.
Thus,

Lazy(Lazy &) = delete;
Lazy(Lazy &&) = delete;
Lazy &operator=(Lazy &) = delete;
Lazy &operator=(Lazy &&) = delete;

Then the following will be the only valid operation:

auto& state = Settings::lazy();
Related