C++ Eliminazione di elementi


Esempio

Eliminazione dell'ultimo elemento:

std::vector<int> v{ 1, 2, 3 };
v.pop_back();                           // v becomes {1, 2}

Eliminazione di tutti gli elementi:

std::vector<int> v{ 1, 2, 3 };
v.clear();                              // v becomes an empty vector

Eliminazione elemento per indice:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin() + 3);                 // v becomes {1, 2, 3, 5, 6}

Nota: per un vector cancella un elemento che non è l'ultimo elemento, tutti gli elementi oltre l'elemento eliminato devono essere copiati o spostati per riempire il vuoto, vedere la nota sotto e std :: list .

Eliminazione di tutti gli elementi in un intervallo:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin() + 1, v.begin() + 5);  // v becomes {1, 6}

Nota: i metodi sopra riportati non modificano la capacità del vettore, ma solo la dimensione. Vedi Dimensioni e capacità del vettore .

Il metodo di erase , che rimuove un intervallo di elementi, viene spesso utilizzato come parte dell'idioma di cancellazione-rimozione . Cioè, prima std::remove mosse alcuni elementi alla fine del vettore, e quindi erase costolette di dosso. Si tratta di un'operazione relativamente inefficiente per qualsiasi indice inferiore all'ultimo indice del vettore, in quanto tutti gli elementi dopo i segmenti cancellati devono essere trasferiti in nuove posizioni. Per applicazioni critiche che richiedono la rimozione efficiente di elementi arbitrari in un contenitore, vedere std :: list .

Eliminazione di elementi in base al valore:

std::vector<int> v{ 1, 1, 2, 2, 3, 3 };
int value_to_remove = 2;
v.erase(std::remove(v.begin(), v.end(), value_to_remove), v.end()); // v becomes {1, 1, 3, 3}

Eliminazione di elementi in base alla condizione:

// std::remove_if needs a function, that takes a vector element as argument and returns true, 
// if the element shall be removed
bool _predicate(const int& element) {
    return (element > 3); // This will cause all elements to be deleted that are larger than 3
}
...
std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(std::remove_if(v.begin(), v.end(), _predicate), v.end()); // v becomes {1, 2, 3}

Eliminazione di elementi di lambda, senza creare una funzione di predicato aggiuntiva

C ++ 11
std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(std::remove_if(v.begin(), v.end(),
     [](auto& element){return element > 3;} ), v.end()
);

Eliminazione di elementi in base alla condizione da un ciclo:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
std::vector<int>::iterator it = v.begin();
while (it != v.end()) {
    if (condition)
        it = v.erase(it); // after erasing, 'it' will be set to the next element in v
    else
        ++it;             // manually set 'it' to the next element in v
}

Mentre è importante non incrementare it in caso di cancellazione, si dovrebbe considerare l'utilizzo di un metodo diverso quando poi cancellare più volte in un ciclo. Considerare remove_if per un modo più efficiente.

Eliminazione di elementi in base alla condizione da un ciclo inverso:

std::vector<int> v{ -1, 0, 1, 2, 3, 4, 5, 6 };
typedef std::vector<int>::reverse_iterator rev_itr;
rev_itr it = v.rbegin();

while (it != v.rend()) { // after the loop only '0' will be in v
    int value = *it;
    if (value) {
        ++it;
        // See explanation below for the following line.
        it = rev_itr(v.erase(it.base()));
    } else
        ++it;
}

Nota alcuni punti per il ciclo precedente:

  • Dato un iteratore inverso it punta a qualche elemento, il metodo base fornisce l'iteratore regolare (non inverso) che punta allo stesso elemento.

  • vector::erase(iterator) cancella l'elemento puntato da un iteratore e restituisce un iteratore all'elemento che ha seguito l'elemento specificato.

  • reverse_iterator::reverse_iterator(iterator) costruisce un iteratore inverso da un iteratore.

Mettere tutto, la linea it = rev_itr(v.erase(it.base())) dice: prendere l'iteratore inverso it , hanno v cancellare l'elemento puntato dal suo iteratore regolare; prendere l'iteratore risultante, costruire un iteratore inverso da esso, e assegnare all'iteratore contrario it .


L'eliminazione di tutti gli elementi mediante v.clear() non libera la memoria (la capacity() del vettore rimane invariata). Per recuperare spazio, utilizzare:

std::vector<int>().swap(v);
C ++ 11

shrink_to_fit() libera la capacità vettoriale inutilizzata:

v.shrink_to_fit();

Il shrink_to_fit non garantisce di reclamare realmente lo spazio, ma la maggior parte delle implementazioni attuali lo fanno.