Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. ATL / WTL / STL
  4. map erase issue

map erase issue

Scheduled Pinned Locked Moved ATL / WTL / STL
helptutorialquestion
10 Posts 8 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    Yu Zhiquan
    wrote on last edited by
    #1

    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; }

    A M J S F 5 Replies Last reply
    0
    • Y Yu Zhiquan

      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; }

      A Offline
      A Offline
      Abebe
      wrote on last edited by
      #2

      don't delete elements from a map while iterating through it, you'll probably end up accessing pairs that are deleted. Er zit een korstje op mijn aars.

      1 Reply Last reply
      0
      • Y Yu Zhiquan

        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; }

        M Offline
        M Offline
        Michael Dunn
        wrote on last edited by
        #3

        When you delete an element, any iterators pointing at that element become invalid. So after calling MyMap.erase(MyIterator) you can't use MyIterator 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.

        1 Reply Last reply
        0
        • Y Yu Zhiquan

          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; }

          J Offline
          J Offline
          Joaquin M Lopez Munoz
          wrote on last edited by
          #4

          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

          M 1 Reply Last reply
          0
          • J Joaquin M Lopez Munoz

            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

            M Offline
            M Offline
            miropl
            wrote on last edited by
            #5

            ... and just one line more. typedef map< char*, int > STRING2INT; instead typedef map STRING2INT; // it's never going to work Miro

            J 1 Reply Last reply
            0
            • M miropl

              ... and just one line more. typedef map< char*, int > STRING2INT; instead typedef map STRING2INT; // it's never going to work Miro

              J Offline
              J Offline
              Joaquin M Lopez Munoz
              wrote on last edited by
              #6

              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 of STRING2INT to the world, another subtler flaw comes to light. The type

              map< 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; // #2

              No 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 a map< string, int >. Regards, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

              M 1 Reply Last reply
              0
              • J Joaquin M Lopez Munoz

                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 of STRING2INT to the world, another subtler flaw comes to light. The type

                map< 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; // #2

                No 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 a map< string, int >. Regards, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

                M Offline
                M Offline
                miropl
                wrote on last edited by
                #7

                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

                Z 1 Reply Last reply
                0
                • M miropl

                  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

                  Z Offline
                  Z Offline
                  ZoogieZork
                  wrote on last edited by
                  #8

                  miropl wrote: _const char* key = str.c_str(); // init that's ok cout< That shouldn't even compile if the type of m is map<char*,int>, since key is a const char* and not a char* (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 of 1. The reason why is the crux of what Joaquín was saying -- it doesn't matter what the char* is pointing to (whether it's a zero-terminated C string or a big buffer of random char crud), the key is treated as a simple char pointer, and thus takes on pointer comparison semantics when used in the map. Here's a simpler example of how things can go wrong with char*:

                  #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_

                  1 Reply Last reply
                  0
                  • Y Yu Zhiquan

                    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; }

                    S Offline
                    S Offline
                    souldog
                    wrote on last edited by
                    #9

                    By the way, if you want to make the map empty then just call clear()

                    1 Reply Last reply
                    0
                    • Y Yu Zhiquan

                      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; }

                      F Offline
                      F Offline
                      f2
                      wrote on last edited by
                      #10

                      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 =-

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups