Ane
Ane

Reputation: 73

Erase element from list of type struct

This is the declaration of my list: list<Message*> g_messages;

where Message is a struct.

I want to delete a certain position of the list (a Message). If it was a vector, I would do it like this:

//delete g_messages[id];

with lists .erase() must be used, but I don't know how.

g_messages.erase(id); doesn't work. It was suggested to use an iterator, but how do I link the const int id and the iterator?

Upvotes: 1

Views: 744

Answers (2)

Jts
Jts

Reputation: 3527

This is how you do it with lists, you have to iterate through all of them, since they r doubly-linked lists (each element contains a pointer to the previous and next element).

// loop through all the elements
for (auto& it = g_messages.begin(); it != g_messages.end(); it++)
{
    if ((*it)->id == input_id)
    {
        delete *it;
        g_messages.erase(it);
        break;
    }
}

Another option would be to use std::find_if from <algorithm> which takes a predicate

auto it = std::find_if(g_messages.begin(), g_messages.end(), [input_id](Message* p){ return (p->id == input_id); });

if (it != g_messages.end())
{
    delete *it;
    g_messages.erase(it);
}

EDIT: as requested by the OP (delete by it's position relative to start)

// loop through all the elements
int i = -1;
for (auto& it = g_messages.begin(); it != g_messages.end(); it++)
{
    if (++i == input_position)
    {
        delete *it;
        g_messages.erase(it);
        break;
    }
}

OR

auto it = g_messages.begin();

if (input_position < g_messages.size())
{
    std::advance(it, input_position);
    g_messages.erase(it);
}

Upvotes: 2

Christophe
Christophe

Reputation: 73376

To erase an element in a list<Message*> you have to do three things:

  • get an iterator that points to the element you want to get rid of. Unfortunately list iterators are bidirectional: you can go to the start or the end of the list and move one single step foarward/backward at a time.
  • delete the object you point to (by the way, it would be safer to use smart pointers instead of raw pointers here: you could then skip this additional step and be sure that you're not leaking memory)
  • erase the element of the list

Here how to do it:

auto it = g_messages.begin();   // iterator to start at begin of list 
it++;it++;              // move two steps forward (i.e. 2x  1 step)
delete *it;             // delete the allocated object you point to 
g_messages.erase(it);   // erase the elemnt in the list.  

Here a quick live demo using smart pointers.

Upvotes: 1

Related Questions