2009-01-25 4 views
2

dire que nous avons:Comment utiliser les "enlevés" éléments après std :: remove_if

struct IsEven { 
    bool operator() (int i) { return i % 2 == 0; } 
}; 

Puis:

vector<int> V; // fill with ints 
vector<int>::iterator new_end = remove_if(V.begin(), V.end(), IsEven()); 
V.erase(new_end, V.end()); 

fonctionne très bien (il laisse V avec seulement les entiers impairs) . Mais il semble que les éléments de new_end à V.end() sont pas les entiers pairs que nous supprimons. Par exemple, si v commence comme 1 4 2 8 5 7, alors je reçois 8 5 7 pour ces éléments (bien qu'après l'appel erase, le vecteur a effectivement 1 5 7 à gauche).

Apparemment, (selon http://www.sgi.com/tech/stl/remove_if.html)

The iterators in the range [new_last, last) are all still dereferenceable, 
but the elements that they point to are unspecified. 

Tout d'abord, WTF? Et deuxièmement, comment puis-je contourner cela sans essentiellement réimplémenter remove_if?

+0

Un conseil connexe dans le cas où vous utilisez un conteneur de pointeurs - utilisez la partition si vous voulez supprimer en utilisant les pointeurs: http://www.ddj.com/architect/184401414 –

Répondre

7

Il semble que vous voulez utiliser partition() pour partitionner le vecteur en groupes de valeurs impaires au début et les valeurs paires à la fin. partition() retournera un itérateur au premier élément du deuxième groupe. En ce qui concerne le WTF, je ne sais pas pourquoi vous attendez une opération de suppression pour conserver les éléments que vous souhaitez supprimer en les copiant (c'est un travail supplémentaire) à la fin du conteneur. La plupart des gens considèrent le WTF dans remove() (et ses cousins) comme étant le fait que la taille du vecteur n'est pas réduite et que vous devez appeler erase() pour supprimer réellement les éléments non désirés après l'opération de suppression.

+0

C'était en fait mon WTF initial, mais Je me suis habitué, et je n'ai pas réalisé que partition() existait. –

+0

Cela a du sens quand on y pense. Un itérateur ne représente qu'une séquence dans un conteneur, pas le conteneur lui-même. Il peut ne pas représenter tous les éléments du conteneur ou les données d'un conteneur. Mais oui, il trébuche souvent les débutants. Et puis ils ont un moment a-ha et * get * STL – jalf

+0

jalf a raison. C'est déroutant au début, mais si remove_if() était capable de se débarrasser des éléments restants, cela signifierait qu'il ne pourrait pas fonctionner avec les tableaux. (Comment est-ce que vous "supprimez des éléments" d'un tableau?) –

2

Je suppose que le point est que la fonction est appelée remove_if pour une raison. Il supprime des éléments. Il ne les déplace pas ou ne les sélectionne pas. Après avoir appelé remove_if, vous n'êtes plus assuré que les éléments que vous avez supprimés existent. Tout ce dont vous avez la garantie, c'est que les éléments entre first et new_last ne contiennent aucun des éléments supprimés.

std::partition serait un meilleur choix, non? Ou peut-être remove_copy_if, en fonction exactement de ce que vous essayez de faire.

2

Si vous voulez vraiment utiliser les éléments "supprimés", vous voulez std::partition.