удаление объектов-элементов стандартного вектора с помощью стирания: а) обработка памяти и б) лучший способ?

У меня есть vec_A, в котором хранятся экземпляры class A как: vec_A.push_back(A());

Я хочу удалить некоторые элементы в векторе на более позднем этапе, и у меня есть два вопроса: а) Элемент удаляется как: vec_A.erase(iterator) Есть ли какой-либо дополнительный код, который мне нужно добавить, чтобы убедиться, что нет утечки памяти? .

b) Предположим, что условие if(num <5) имеет место, если num входит в определенный список номеров. Учитывая это, есть ли лучший способ удалить элементы вектора, чем то, что я иллюстрирую ниже?

#include<vector>
#include<stdio.h>
#include<iostream>

class A {
      public:

             int getNumber();            
             A(int val);
             ~A(){};
      private:
              int num;
};

A::A(int val){
         num = val;
         };

int A::getNumber(){
    return num;
};

int main(){


    int i  =0;
    int num;
    std::vector<A> vec_A;
    std::vector<A>::iterator iter;

          for ( i = 0; i < 10; i++){
              vec_A.push_back(A(i));
          }
          iter = vec_A.begin();

          while(iter != vec_A.end()){
              std::cout <<  "\n --------------------------";
              std::cout <<  "\n Size before erase =" << vec_A.size();
              num = iter->getNumber() ;
              std::cout <<  "\n num = "<<num;
              if (num < 5){
                      vec_A.erase(iter);
                      }
              else{
                   iter++;
                   }

              std::cout <<  "\n size after erase =" << vec_A.size();
          }        


    std::cout << "\nPress RETURN to continue...";
    std::cin.get();

    return 0;
}

person memC    schedule 30.04.2010    source источник


Ответы (2)


a) Элемент удаляется как: vec_A.erase(iterator) Есть ли какой-либо дополнительный код, который мне нужно добавить, чтобы убедиться, что нет утечки памяти? .

Да, это все, что вам нужно сделать. Утечек памяти не будет. Поскольку вы не разместили свой объект в куче, когда вы сделали vec_A.push_back(A()), новый объект скопирован в вектор. Когда вы стираете, вектор позаботится об удалении элементов.

Предположим, что условие if(num ‹5) равносильно тому, что num входит в определенный список номеров. Учитывая это, есть ли лучший способ удалить элементы вектора, чем то, что я иллюстрирую ниже?

Да, вы можете удалить/стереть идиому. Вот пример:

 class A
{
public:
    A(int n) : m_n(n)
    {
    }

    int get() const
    {
        return m_n;
    }
private:
    int m_n;
};

bool lessThan9(const A& a)
{
    return a.get() < 9;
}

//Or if you want for a generic number
struct Remover : public std::binary_function<A,int,bool>
{
public:
    bool operator()(const A& a, int n)const
    {
        return a.get() < n;
    }
};

int main()
{
    std::vector<A> a;
    a.push_back(A(10));
    a.push_back(A(8));
    a.push_back(A(11));
    a.push_back(A(3));

    a.erase(std::remove_if(a.begin(), a.end(), lessThan9), a.end());

    //Using the user-defined functor
    a.erase(std::remove_if(a.begin(), a.end(), std::bind2nd(Remover(), 9)), a.end());

    return 0;
}
person Naveen    schedule 30.04.2010
comment
Почему бы просто не a.erase(std::remove_if(a.begin(), a.end(), lessThan9), a.end()); - person Andreas Brinck; 30.04.2010
comment
Спасибо, Навин! Это очень полезно. .Кроме того, спасибо Андреасу за дополнительный комментарий. Я думаю, что Навин обновил свой код. - person memC; 30.04.2010

1) Обработка ресурсов осуществляется самим классом. Деструктор класса отвечает за отсутствие утечки памяти.

2) Удаление элементов из вектора лучше всего выполнять в обратном порядке:

for (std::vector<A>::reverse_iterator it = vec_A.rend(); it != vec_A.rbegin(); --it)
{
  if (it->getNumber() < 5) {vec_A.erase(it.base());}
}
person Michael Ulm    schedule 30.04.2010
comment
это (стирание сзади наперед) полезно знать, хотя у меня не всегда есть условие if ( num ‹5) . - person memC; 30.04.2010
comment
Я не понимаю, почему вы думаете, что удаление задом наперед значительно лучше. Лучше всего это сделать с помощью идиомы удаления-стирания (которая делает всю операцию однопроходной). - person UncleBens; 30.04.2010
comment
Недостатком идиомы «удалить-стирать» является необходимость использования предиката. Мне не нравится писать функцию lessThan5 только для одного стирания. Сказав это, я выбираю идиому remove-erase, если предикат уже существует или может быть использован повторно (или если у меня есть лямбда-выражения). - person Michael Ulm; 30.04.2010