Search code examples
c++qt4qlist

Remove elements from QList of pointers


I have a QList variable. How can I erase all the elements starting from an X index and removing all the subsequents N elements taking care of freeing also the memory?


Solution

  • First of all, you should never use MyClass* to "own" (i.e. control the lifetime of) an instance of MyClass. Thus, a list of MyClass* shouldn't "own" any instances of MyClass, either. Thus you wouldn't ever use the delete operator with any of these pointers (and a stray delete outside a smartpointer implementation should almost always raise a few eyebrows).

    QList is in fact a type optimized for a similar use-case. A QList<MyClass> will internally store a dynamic array of MyClass* (if MyClass is larger than a pointer), so re-ordering and expanding the list is potentially cheaper. However, if you need to remove elements from the list without deleting them, you should use a QList<unique_ptr<MyClass>> or similar. Either way, you wouldn't have to worry about the objects' lifetimes; you'd only need to remove them from the list.

    Now that I said that, there are a few useful STL idioms that will help achieving what you're looking for, and they also apply to (most) Qt containers (edit: fixed the removal, added a few helpful comments):

    QList<MyClass*> myList; //TODO FIXME XXX: clarify mentioned ownership issues
    assert(X + N <= myList.size());
    
    // this is the range of objects we want to remove and delete
    // (N elements, starting from index X)
    auto range_begin = myList.begin() + X,
         range_end = range_begin + N;
    // delete each object in range
    std::for_each(range_begin, range_end, [](MyClass* ptr) { delete ptr; });
    // remove them from the list
    myList.erase(range_begin, range_end);
    

    It's even simpler still, if you meant to remove all elements after myList[X - 1] (in short, replace range_end with myList.end()).