C++ Marking objects for removal in STD list via nullptrs -
i wondering if accaptable practice:
struct item { }; std::list<std::shared_ptr<item>> items; std::list<std::shared_ptr<item>> removeditems; void update() { items.push_back(std::make_shared<item>()); // sample item (auto itemiterator=items.begin();itemiterator!=items.end();itemiterator++) { if (true) { // complex condition, (true) demo purposes removeditems.push_back(std::move(*itemiterator)); // move ownership *itemiterator=nullptr; // set current item nullptr } // 1 of downsides, have check if // current iterator value not nullptr if (*itemiterator!=nullptr) { // complex loop items collection modified } } // after loop done, can safely remove our objects removeditems.clear(); // calls destructors on objects //finally clear items nullptr items.erase( std::remove_if( items.begin(), items.end(), [](const std::shared_ptr<item>& itemtocheck){ return itemtocheck==nullptr; }), items.end() ); }
the idea here we're marking items container effected outside sources. when item removed container, it's set nullptr moved removeditems before that.
something event might effect items
, add/remove items, had come solution.
does seem idea?
i think complicating things much. if in multi-threaded situation (you didn't mention in question), need locks guarding reads other threads access modified lists. since there no concurrent data structures in standard library, need add such stuff yourself.
for single-threaded code, can call std:list
member remove_if
predicate. there no need set pointers null, store them , multiple passes on data.
#include <algorithm> #include <list> #include <memory> #include <iostream> using item = int; int main() { auto lst = std::list< std::shared_ptr<item> > { std::make_shared<int>(0), std::make_shared<int>(1), std::make_shared<int>(2), std::make_shared<int>(3), }; // shared_ptrs elements auto x0 = *std::next(begin(lst), 0); auto x2 = *std::next(begin(lst), 2); // erase numbers lst.remove_if([](std::shared_ptr<int> p){ return *p % 2 == 0; }); // numbers have been erased (auto = begin(lst); != end(lst); ++it) std::cout << **it << ","; std::cout << "\n"; // shared pointers members still valid std::cout << *x0 << "," << *x2; }
note elements have been erased list, not put @ end of list. latter effect standard algorithm std::remove_if
do, , after have call std::list
member function erase
. two-step erase-remove idiom looks this
// move numbers end of list in unspecified state auto res = std::remove_if(begin(lst), end(lst), [](std::shared_ptr<int> p){ return *p % 2 == 0; }); // erase numbers lst.erase(res, end(lst));
however, in both cases, underlying item
elements have not been deleted, since each still have shared pointer associated them. if refence counts drop zero, former list elements deleted.
Comments
Post a Comment