Изтриване на C++ структура от STL списък с помощта на итератор

Имам тази програма за тестване. Не знам как да изтрия структура в списъка с помощта на итератор.

#include<iostream>
#include<list>
using namespace std;
typedef struct Node
{
    int * array;
    int id;
}Node;

void main()
{
    list<Node> nlist;
    for(int i=0;i<3;i++)
    {
        Node * p = new Node;//how to delete is later?

        p->array = new int[5];//new array
        memset(p->array,0,5*sizeof(int));

        p->id = i;

        nlist.push_back(*p);//push node into list
    }

    //delete each struct in list
    list<Node>::iterator lt = nlist.begin();
    while( lt != nlist.end())
    {
        delete [] lt->array;

        delete &(*lt);//how to delete the "Node"?

        lt++;
    }
}

Знам как да изтрия структурата отделно. Това е така:

Node * p = new Node;
p->array = new int[5];

delete [] p->array; //delete the array
delete p;//delete the struct

Въпреки това, когато се върне обратно в списъка, не знам как да го изтрия според итератора на списъка.

list<Node>::iterator lt = nlist.begin();
while( lt != nlist.end())
{
    delete [] lt->array;

    delete &(*lt);//how to delete the "Node"?

    lt++;
}

person Terry    schedule 24.12.2012    source източник
comment
Защо го разпределяте динамично на първо място?   -  person chris    schedule 24.12.2012
comment
това е само пример, моята програма не е такава.   -  person Terry    schedule 25.12.2012


Отговори (3)


Тъй като декларирате списъка с list<Node>, когато правите:

nlist.push_back(*p)

всъщност създава Node() и копира данните от възела, който току-що сте разпределили динамично, но не използва действителния указател. И след това се опитвате да изтриете указател от обекта, който системата автоматично ще изтрие:

delete &(*lt); // this causes double free

Трябва да декларирате списъка като list<Node*>, така че указателят да бъде вмъкнат в списъка. Въпреки че не трябва наистина да се занимавате с този вид разпределение в c++, с няколко модификации вашият код трябва да работи:

int main()
{
  list<Node*> nlist;
  for(int i=0;i<3;i++)
  {
    Node *p = new Node;//how to delete is later?

    p->array = new int[5];//new array
    memset(p->array,0,5*sizeof(int));

    p->id = i;

    nlist.push_back(p);//push node into list
  }

  //delete each struct in list
  list<Node*>::iterator lt = nlist.begin();
  while( lt != nlist.end())
  {
    delete [] (*lt)->array;

    delete *lt;//how to delete the "Node"?

    lt++;
  }

  return 0;
}
person perreal    schedule 24.12.2012
comment
Благодаря ви много, сега знам причината. - person Terry; 25.12.2012

Можете да използвате изтриване на списък, за да изтриете възел от всяко място между списъка .

list<Node>::iterator it = nlist.begin();
advance(it,n); \\n is the node you want to delete, make sure its less than size of list
it = mylist.erase (it); 

Като алтернатива, ако искате да изтриете елементи от двата края на списъка, можете да използвате pop_back или членските функции на pop_front.

person Ajay Nair    schedule 24.12.2012

използвайте list.erase Но вие наистина правите този начин, различен от C++. Не е нужно да разпределяте int[5] с new. Писането на int[5] прави това, което искате. Вашият тип възел, дефиниран в c-way. В c++ не е необходимо да го обвивате с typedef

person kassak    schedule 24.12.2012
comment
о, да, писах C много и се опитвах да науча C++. Разпределете int[5], защото имам нужда от тях да бъдат динамично разпределение. - person Terry; 25.12.2012