map erase issue
-
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
-
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
-
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
When you delete an element, any iterators pointing at that element become invalid. So after calling
MyMap.erase(MyIterator)
you can't useMyIterator
again (like in the++
expression) unless you reset it first. --Mike-- Ericahist | CP SearchBar v2.0.2 | Homepage | RightClick-Encrypt | 1ClickPicGrabber There is a saying in statistics that a million monkeys pounding on typewriters would eventually create a work of Shakespeare. Thanks to the Internet, we now know that this is not true. -
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
Just to add to the previous comments, the following
for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); )
{
MyMap.erase(MyIterator++);
}is correct. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
-
Just to add to the previous comments, the following
for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); )
{
MyMap.erase(MyIterator++);
}is correct. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
-
... and just one line more. typedef map< char*, int > STRING2INT; instead typedef map STRING2INT; // it's never going to work Miro
I didn't see the declaration of
STRING2INT
, as the original poster forgot to tick the "Do not treat <'s as HTML tags" checkbox :) Now that you have revealed the definition ofSTRING2INT
to the world, another subtler flaw comes to light. The typemap< char*, int >
does not guarantee the behavior one would assume at first sight. Even worse, it can seem to work until less expected. The problem is that what's being used as a key are pointers to chars, and pointing to equivalent contents does not imply pointer equality. Consider:
typedef map< char*, int > STRING2INT;
STRING2INT m;
m["January"]=1; // #1
cout<<m["January"]<<endl; // #2No guarantee is made that the first pointer in #1 is the same as that in #2. Usually, this equality happens to work because the compiler is smart enough not to duplicate literals, but the following will fail for sure
m["January"]=1;
string str="January";
cout<<m[str.c_str()]<<endl;Of course, the simple solution is to define
STRING2INT
as amap< string, int >
. Regards, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo -
I didn't see the declaration of
STRING2INT
, as the original poster forgot to tick the "Do not treat <'s as HTML tags" checkbox :) Now that you have revealed the definition ofSTRING2INT
to the world, another subtler flaw comes to light. The typemap< char*, int >
does not guarantee the behavior one would assume at first sight. Even worse, it can seem to work until less expected. The problem is that what's being used as a key are pointers to chars, and pointing to equivalent contents does not imply pointer equality. Consider:
typedef map< char*, int > STRING2INT;
STRING2INT m;
m["January"]=1; // #1
cout<<m["January"]<<endl; // #2No guarantee is made that the first pointer in #1 is the same as that in #2. Usually, this equality happens to work because the compiler is smart enough not to duplicate literals, but the following will fail for sure
m["January"]=1;
string str="January";
cout<<m[str.c_str()]<<endl;Of course, the simple solution is to define
STRING2INT
as amap< string, int >
. Regards, Joaquín M López Muñoz Telefónica, Investigación y DesarrolloYes, char* is difficult to manipulate, but char* also is a pointer to null terminated string - the basic C/C++ strings primitive type (well know "C" string). A little modification of "The problem is that what's being used as a key are pointers to chars". No the key are pointers to null terminated strings. Now let's see the code. typedef map STRING2INT; // Thank's Mike m["January"]=1; string str="January"; // cout< 012345678901 the next (12) byte is '\0' // |||||||||||| char somearr[] ="MonthJanuary"; char* psomearr = &somearr[5]; // lets take the address of the fifth byte char** ppkey = &psomearr; // let's try indirect cout<. Best regards, Miro
-
Yes, char* is difficult to manipulate, but char* also is a pointer to null terminated string - the basic C/C++ strings primitive type (well know "C" string). A little modification of "The problem is that what's being used as a key are pointers to chars". No the key are pointers to null terminated strings. Now let's see the code. typedef map STRING2INT; // Thank's Mike m["January"]=1; string str="January"; // cout< 012345678901 the next (12) byte is '\0' // |||||||||||| char somearr[] ="MonthJanuary"; char* psomearr = &somearr[5]; // lets take the address of the fifth byte char** ppkey = &psomearr; // let's try indirect cout<. Best regards, Miro
miropl wrote: _const char* key = str.c_str(); // init that's ok cout< That shouldn't even compile if the type of
m
ismap<char*,int>
, sincekey
is aconst char*
and not achar*
(as referenced in the template). In fact, on VS.NET 2k3 and GCC 3.2.3, the following code:#include <map>
#include <iostream>using namespace std;
typedef map<const char*,int> mymap_t;
int main(int argc, char* argv[]) {
mymap\_t m; m\["January"\]=1; string str="January"; const char\* key = str.c\_str(); cout << m\[key\] << endl; return 0;
}
Prints out
0
instead of1
. The reason why is the crux of what Joaquín was saying -- it doesn't matter what thechar*
is pointing to (whether it's a zero-terminated C string or a big buffer of randomchar
crud), the key is treated as a simplechar
pointer, and thus takes on pointer comparison semantics when used in themap
. Here's a simpler example of how things can go wrong withchar*
:#include <conio.h>
#include <map>
#include <iostream>using namespace std;
typedef map<char*,int> mymap_t;
int _tmain(int argc, _TCHAR* argv[]) {
mymap\_t m; m\["January"\]=1; char \*str = strdup( "January" ); cout << m\[str\] << endl; // Prints out 0, not 1. free(str); return 0;
}
- Mike_
-
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
-
When I use map erase in "for", it will be error, I do not know the reason, who can tell me details, and how to correct it? thanks a lot! following is code: #pragma warning(disable:4786) #include #include #include using namespace std ; typedef map STRING2INT; void main() { STRING2INT MyMap; STRING2INT::iterator MyIterator; MyMap["January"] = 1; MyMap["February"] = 2; MyMap["March"] = 3; MyMap["April"] = 4; MyMap["May"] = 5; MyMap["June"] = 6; MyMap["July"] = 7; MyMap["August"] = 8; MyMap["September"] = 9; MyMap["October"] = 10; MyMap["November"] = 11; MyMap["December"] = 12; for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); } cout << MyMap.size() << endl; }
Yu Zhiquan wrote:
for (MyIterator = MyMap.begin(); MyIterator!=MyMap.end(); MyIterator++) { MyMap.erase(MyIterator); }
the moment u call MyMap.erase(MyIterator), the size is reduced and begin() has changed. so in your for loop, MyIterator++ is directing u to the "3rd" element. u should use while loop to delete by check the size, not begin till end. from, -= aLbert =-