Re: __gnu_cxx::hash_map question, please help!!!
On Oct 26, 1:34 am, aaragon <alejandro.ara...@gmail.com> wrote:
On Oct 25, 4:58 am, James Kanze <james.ka...@gmail.com> wrote:
[...]
I actually managed to make my code work by not using that loop. I
actually store temporarily in a vector those values that need to be
removed and then I do a loop over the vector to remove them (not using
the hash_map iterators). This works perfectly.
That's one way to do it. IMHO, the hard way. The classical
approach, I think, is somethink like:
Map::iterator current = myMap.begin() ;
while ( current != myMap.end() ) {
if ( someCondition ) {
myMap.erase( current ++ ) ;
// NOTE: current incremented before the erase!!
else {
++ current ;
}
}
Note that this is valid for the associateve containers, where
erase only invalidates iterators to the object erased, and
doesn't return the next iterator. For the sequences, where
erase may invalidate other iterators (including one to the
following element), but returns an iterator to the first element
following the one erased, you would write:
while ( current != myContaner.end() ) {
if ( someCondition ) {
current = myContaner.erase( current ) ;
else {
++ current ;
}
}
Note too that in both cases, you specify the element to be
removed by the iterator; you don't need to extract the key and
do a second look-up.
What I don't understand is why it did work with the std::map.
It's undefined behavior, so it might work, sometimes. Without
looking at the implementation, I would guess that the iterator
contains a pointer to the node, and the node contains whatever
information is necessary for iterating (perhaps indirectly, in
the form of a pointer to the parent node). The erase function
has freed the node, but the actual memory hasn't been
overwritten. Depending on the implementation, you may iterate
to the next element, or possibly, in special cases, skip an
element or visit one twice (if the iteration is done by going up
to the parent iterator, and the tree has been reorganized as a
result of the erase).
Why it didn't work with the hash map is probably due to the fact
that the nodes are organized differently. You'd have to look at
the details of the implementation to know why one crashed, and
the other seemed to work.
And of course, a slightly different implementation, and you
could end up with std::map crashing, and the hash_map working.
That's the fun of undefined behavior.
I will add those options for compilation (yes I'm using g++ on
Ubuntu linux). Are there any other useful compilation options
to add?
Doubtlessly:-). The first time I use a compiler, I study every
possible option, to see which ones I'm interested in. (For g++,
see http://www.gnu.org/software/gcc/onlinedocs/.) Note that the
compiler documentation isn't always complete,
however---especially if you consider the standard library as
part of the compiler; for g++, for example, you'll also want to
check the library documentation (libstdc++-v3: there's also a
link to it on the page above---the chapter "Preprocessor macros
controlling the library" is the one which interests you).
Finding this information isn't always trivial, but is IMHO
essential. Exactly which options you want will depend on what
you are doing. (I have to deal with a lot of legacy code, for
example, so I often need options which support older constructs.)
Some of the options you might be interested in:
-std=c++98 -no-nonansi-builtins -fuse-cxa-atexit
For maximum standards conformance. (If you need to support
legacy code, you may need to add options here which "undo"
some conformance.)
-no-threadsafe-statics
Doesn't work correctly for Sparc anyway (haven't verified
Intel), and isn't portable, so you're probably better off
without it. It does mean that you'll have to worry about
the issue yourself, however.
There are also tons of options controling warnings.
Classically, the recommendation is to use -Wall -Wextra
-pedantic; I find it better to go through the entire list, and
specify each one independantly, according to my personal opinion
as to what is right, and what isn't. (I don't use -Wall, for
example, because it contains -Wmissing-braces, which generates a
warning whenever I use PTHREAD_MUTEX_INITIALIZER under Solaris.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34