I have a global vector of unique_ptrs to a base class, to which I append unique_ptrs to a derived class:
std::vector<std::unique_ptr<Base>> global_vec;
template<typename T>
Base* create_object()
{
std::unique_ptr<T> uptr = std::make_unique<T>(/* ... */);
Base* last_ptr = uptr.get();
global_vec.emplace_back(std::move(uptr));
return last_ptr; /*this is a bit irrelevant, but is for the caller*/
}
Now, Base itself has a member vector of raw pointers to Base:
struct Base
{
...
std::vector<Base*> providers;
...
}
The pointers that make up Base::providers are all obtained via calling unique_ptr::get() from global_vec:
void Base::subscribe_to(Base* src)
{
providers.push_back(src);
}
Base has a member function that does work with these subscribers, and checks for nullptr before doing work:
void Base::do_work()
{
...
for(Base* ptr : providers)
{
if(ptr != nullptr)
{
...
}
}
}
Now, somewhere else in my code, I can erase the unique_ptrs in global_vec:
auto itr = std::find_if(global_vec.begin(), global_vec.end(), [&](std::unique_ptr<Base> const& n)
{ return n.get() == ptr_selected; }); //ptr_selected points to a widget selected by the user
global_vec.erase(itr);
However, after erasing an element, Base::suscribers will still hold a valid pointer to an object. That is, when iterating through Base::providers in Base::do_work(), no Base* will equal std::nullptr.
I would expect that erasing a unique_ptr from global_vec would invoke Base::~Base(), thus rendering the pointers in Base::providers as std::nullptr. Base's destructor is invoked, but the pointers are valid (you can even get access to data members from them).
Base does have a virtual destructor.
Why are the pointers in Base::providers still valid?
get
returns by value! – Kerrek SB