0

I have a singleton class A that the user interacts with. A stores shared pointers to a separate class B. And within A::doStuff(), it allows B to delete B from the vector in A that stores the shared pointers.

However, I can't seem to find a way for B to inform A about itself. In short, what A stores != what B informs A to delete from itself.

Right now I am just using std::make_shared<B>(*this) such that the syntax matches but this creates a new instance of B which doesn't match with b in main, hence failure for A to remove it.

struct B
{
    void doStuff()
    {
        // stuff...

        // and then delete itself from A::_vec
        A::get().del(std::make_shared<B>(*this)); 

        // with raw ptr, I would do `A::get().del(this);
    }
};

Here's the sample code that prints use_count to help identify whether the same object is attempted to be removed from A.

I'd expect the shared count at the end of the program to be 1, but it's 2.

class B;

class A
{
    std::vector<std::shared_ptr<B>> _vec;

    public:
    static A& get();
    void run();
    void add(std::shared_ptr<B> b);
    void del(std::shared_ptr<B> b);
};

struct B
{
    void doStuff()
    {
        // stuff...

        // and then delete itself from A::_vec
        A::get().del(std::make_shared<B>(*this));
        
        // A::get().del(this);  // would do this with raw pointer!
    }
};


A& A::get()
{
    static A obj;
    return obj;
}

void A::run()
{
    for (auto e : _vec)
    {
        e->doStuff();
    }
}

void A::add(std::shared_ptr<B> b)
{
    std::cout << "A::add[1] = " << b.use_count() << std::endl;
    _vec.push_back(b);
    std::cout << "A::add[2] = " << b.use_count() << std::endl;
}

void A::del(std::shared_ptr<B> b)
{
    // removing b from _vec
    std::cout << "\n_vec size1 = " << _vec.size() << std::endl;
    std::cout << "A::del[1] = " << b.use_count() << std::endl;

    _vec.erase(std::remove(_vec.begin(), _vec.end(), b), _vec.end());
    // _vec size remains 1 since "b" != what's in _vec

    std::cout << "A::del[2] = " << b.use_count() << std::endl;
    std::cout << "_vec size2 = " << _vec.size() << std::endl << std::endl;
}


int main() 
{
    auto b = std::make_shared<B>();
    A::get().add(b);

    std::cout << "After add = " << b.use_count() << std::endl;   

    A::get().run();

    // remains 2 since _vec.erase wasn't successful!
    std::cout << "After remove = " << b.use_count() << std::endl;  
}
xyf
  • 664
  • 1
  • 6
  • 16
  • You could just pass a raw pointer to `del` no need for it to be a shared pointer as `del` isn't storing the passed in value – Alan Birtles Dec 10 '22 at 02:40

0 Answers0