vendredi 1 octobre 2021

C++ shared_from_this() is not letting obj get destructed

I have a following piece of code, which is creating a simple object of Name and inside that it is creating another object Name, with a shared_from_this() reference. As I am reading from here https://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this

"Effectively executes std::shared_ptr(weak_this), where weak_this is the private mutable std::weak_ptr member of enable_shared_from_this."

Which I am understanding as shared_from_this() is only creating a weak pointer to shared obj. But I don't see this is the case in runtime. There is effectively a circular reference getting created.

At the end of the I was expecting the Name obj should be destructed, but it is not because the reference counter is 2.

Can someone help me understand how should I use enable_shared_from_this(), that can effectively cleanup the Name obj, once it goes out of reference.

#include <iostream>
#include <memory>
#include <string>
#include <chrono>
#include <thread>

using namespace std;

struct Another;
struct Name : public std::enable_shared_from_this<Name> {
    std::string t;
    int m, n, p;
    shared_ptr<Another> ann;
    Name() {
        std::cout << "constructor\n";
    }
    void MakeSomething() {
        ann = std::make_shared<Another>(shared_from_this());
    }
    ~Name() {
        std::cout << "destructor\n";
    }
};

struct Another {
    shared_ptr<Name> nn;
    Another(shared_ptr<Name> n) : nn(n) {
        std::cout << "from another constructor " << nn.use_count() << "\n";
    }
    ~Another() {
        std::cout << "from another destructor\n";
    }
};

int main()
{
    {
        auto n = std::make_shared<Name>();
        std::cout << "Name ref count so far: " << n.use_count() << "\n";

        auto p = n.get();
        //delete p;
        std::cout << "Name ref count so far: " << n.use_count() << "\n";

        n->MakeSomething();
        std::cout << "Name ref count so far: " << n.use_count() << "\n";
        {
            shared_ptr<Name> m = n;
            std::cout << "Name ref count so far: " << n.use_count() << "\n";
        }

        std::cout << "Name ref count so far: " << n.use_count() << "\n";
    }
    // problem: at this point Name obj, should go out of reference and destructor to be called, which is NOT happening

    return 0;
}

And here is the runtime output (compiler used msvc)

constructor
Name ref count so far: 1
Name ref count so far: 1
from another constructor 3
Name ref count so far: 2
Name ref count so far: 3
Name ref count so far: 2

Aucun commentaire:

Enregistrer un commentaire