2010-07-26 7 views
5

Ceci est une suite à une question précédente que j'avais (Complexity of STL max_element).effacer l'élément max du jeu STL

Je veux faire ressortir l'élément max d'un ensemble, mais je rencontre des problèmes.

est ici à peu près mon code:

set<Object> objectSet; 

Object pop_max_element() { 
    Object obj = *objectSet.rbegin(); 
    set<Object>::iterator i = objectSet.end()--; //this seems terrible 
    objectSet.erase(i); //*** glibc detected *** free(): invalid pointer 
    return obj; 
} 

Plus tôt j'ai essayé objectSet.erase(objectSet.rbegin()); mais le compilateur se plaint qu'il n'y avait pas de fonction concordante (je devine qu'il n'aime pas le reverse_iterator). Je sais qu'il n'y a pas de vérification pour un ensemble vide, mais ça échoue quand objectSet.size() >> 0.

+0

'* objectSet.rbegin();' est-ce une faute de frappe? vous déréférencer l'ensemble? –

+1

Non, c'est l'itérateur qui est déréférencé. Le point se lie plus étroitement que l'étoile. –

Répondre

9

Vous êtes assez proche, mais vous essayez d'en faire un peu trop dans cette tâche d'itérateur. Vous appliquez l'opérateur post-décrément à tous les renvois end. Je ne suis pas vraiment sûr de ce que ça fait, mais ce n'est certainement pas ce que vous voulez. Affectez le résultat end à i et puis décrémentez-le pour obtenir le dernier élément de l'ensemble.

set<Object>::iterator i = objectSet.end(); 
--i; 
Object obj = *i; 
objectSet.erase(i); 
return obj; 
5

Vous devez faire ceci:

set<Object> objectSet; 

Object pop_max_element() { 
    Object obj = *objectSet.rbegin(); 
    set<Object>::iterator i = --objectSet.end(); // NOTE: Predecrement; not postdecrement. 
    objectSet.erase(i); //*** glibc detected *** free(): invalid pointer 
    return obj; 
} 
5

La déclaration

set<Object>::iterator i = objectSet.end()--; 

signifie 'fin Assign() à i puis décrémenter une variable temporaire qui est sur le point d'être jeté' . En d'autres termes, c'est la même chose que set<Object>::iterator i = objectSet.end();, et je suis sûr que vous reconnaissez que vous ne pouvez pas effacer end(), car il pointe vers un après la fin. Utilisez quelque chose comme ceci:

assert(!objectSet.empty()); // check there is something before end 
set<Object>::iterator i = objectSet.end(); 
--i; 
objectSet.erase(i); 

et qui est bien, il est un moyen légitime de reproduire essentiellement .back() pour un ensemble.

De plus, les itérateurs inverses ont un base() membre à convertir en un itérateur normal et je suppose que vous ne pouvez effacer que les itérateurs normaux - essayez objectSet.erase(objectSet.rbegin().base()).

+0

J'ai essayé le rbegin(). Base(), en vain. – sas4740

+3

'rbegin(). Base()' est identique à 'end()'. –