Clarification for std::vector and std::map

Discussion in 'C++' started by Jonathan Mcdougall, Jul 30, 2003.

  1. On Wed, 30 Jul 2003 18:13:48 -0400, "Victor Bazarov"
    <> wrote:

    >"Sir_Ciph3r" <> wrote...
    >> Can someone explain what is happening in the following code?

    >
    >Undefined behaviour.
    >
    >> #include <iostream>
    >> #include <vector>
    >> #include <map>
    >>
    >> using namespace std;
    >>
    >> int main()
    >> {
    >> vector<int> v;
    >> map<char*,int*> m;
    >>
    >> v.push_back(99);
    >> m["TEST"]=&v[0];

    >
    >You're saving a pointer to an object that may vanish into thin
    >air at any point and the map won't know about it. That's called
    >"asking for trouble".


    I was just wondering if

    map<char*, int> m;

    m["TEST"] = 4;
    m["TEST"] = 6;

    is guaranteed to work, knowing that "TEST" is a pointer to a c-style
    string. To me, it seems that a compiler is allowed to have two
    different "TEST" strings and to map the values to the pointer address,
    no?


    Jonathan
    Jonathan Mcdougall, Jul 30, 2003
    #1
    1. Advertising

  2. Jonathan Mcdougall

    Sir_Ciph3r Guest

    Can someone explain what is happening in the following code?

    #include <iostream>
    #include <vector>
    #include <map>

    using namespace std;

    int main()
    {
    vector<int> v;
    map<char*,int*> m;

    v.push_back(99);
    m["TEST"]=&v[0];

    cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;

    v.erase(&v[0]);

    cout<<"Map: "<<*m["TEST"]<<endl;

    cout<<"Vec size: "<<v.size()<<endl;

    return 0;
    }

    I don't understand why I am getting "99" from this line of code

    cout<<"Map: "<<*m["TEST"]<<endl;

    I erased the vector element and the map only contained the address to
    that vector element...yet I am still getting the value I pushed_back.
    What is happening behind the scenes? Is this code safe?

    Any help would be appreciated
    Sir_Ciph3r, Jul 30, 2003
    #2
    1. Advertising

  3. "Sir_Ciph3r" <> wrote...
    > Can someone explain what is happening in the following code?


    Undefined behaviour.

    > #include <iostream>
    > #include <vector>
    > #include <map>
    >
    > using namespace std;
    >
    > int main()
    > {
    > vector<int> v;
    > map<char*,int*> m;
    >
    > v.push_back(99);
    > m["TEST"]=&v[0];


    You're saving a pointer to an object that may vanish into thin
    air at any point and the map won't know about it. That's called
    "asking for trouble".

    > cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
    >
    > v.erase(&v[0]);


    There is no 'erase' member that takes a pointer to int. If your
    implementation _happens_ to have vector::iterator the same as
    a pointer to the contained type, it doesn't mean it will work
    on any other computers/compilers/platforms. You have to pass
    an iterator to 'erase'.

    >
    > cout<<"Map: "<<*m["TEST"]<<endl;


    After the 'erase' (which probably worked by some weird chance)
    you're trying to dereference a pointer that doesn't exist any
    longer. The behaviour is undefined. You get your 99, but you
    could as well get flying nasal demons.

    >
    > cout<<"Vec size: "<<v.size()<<endl;
    >
    > return 0;
    > }
    >
    > I don't understand why I am getting "99" from this line of code
    >
    > cout<<"Map: "<<*m["TEST"]<<endl;
    >
    > I erased the vector element and the map only contained the address to
    > that vector element...yet I am still getting the value I pushed_back.
    > What is happening behind the scenes?


    Impossible to say. Your code causes undefined behaviour.

    > Is this code safe?


    Absolutely not.

    Victor
    Victor Bazarov, Jul 30, 2003
    #3
  4. Jonathan Mcdougall

    ES Kim Guest

    "Sir_Ciph3r" <> wrote in message
    news:...
    > Can someone explain what is happening in the following code?
    >
    > #include <iostream>
    > #include <vector>
    > #include <map>
    >
    > using namespace std;
    >
    > int main()
    > {
    > vector<int> v;
    > map<char*,int*> m;
    >
    > v.push_back(99);
    > m["TEST"]=&v[0];
    >
    > cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
    >
    > v.erase(&v[0]);
    >
    > cout<<"Map: "<<*m["TEST"]<<endl;
    >
    > cout<<"Vec size: "<<v.size()<<endl;
    >
    > return 0;
    > }
    >
    > I don't understand why I am getting "99" from this line of code
    >
    > cout<<"Map: "<<*m["TEST"]<<endl;
    >
    > I erased the vector element and the map only contained the address to
    > that vector element...yet I am still getting the value I pushed_back.
    > What is happening behind the scenes? Is this code safe?
    >
    > Any help would be appreciated
    >
    >


    A container of raw pointers is usually not a good idea.
    Use string and iterator instead of char* and int*.

    int main()
    {
    vector<int> v;
    map<string, vector<int>::iterator> m;

    v.push_back(99);
    m["TEST"]=v.begin();

    cout<<"Vec size: "<<v.size()<<" : "<<v[0]<<endl;
    cout<<"Map: "<<*m["TEST"]<<endl;

    v.erase(v.begin());

    // cout<<"Map: "<<*m["TEST"]<<endl;
    // v.erase() invalidates m["TEST"]

    cout<<"Vec size: "<<v.size()<<endl;

    return 0;
    }

    --
    ES Kim
    ES Kim, Jul 30, 2003
    #4
  5. Jonathan Mcdougall

    Default User Guest

    Sir_Ciph3r wrote:

    > I erased the vector element and the map only contained the address to
    > that vector element...yet I am still getting the value I pushed_back.
    > What is happening behind the scenes? Is this code safe?



    You did all kinds of undefined behavior. Iterators and pointers into
    vectors are invalidated as soon as you do any kind of operation on the
    vector that make cause it to resize memory. Erase() certainly could have
    done that. What probably happened with that the vector saw that you were
    erasing the last element, so it just backed its valid end pointer by
    one, and decreased the size so that the element you are pointing to will
    be overwritten the next time.

    What are you trying to accomplish?




    Brian Rodenborn
    Default User, Jul 31, 2003
    #5
  6. Jonathan Mcdougall

    Sir_Ciph3r Guest

    On Wed, 30 Jul 2003 18:13:48 -0400, "Victor Bazarov"
    <> wrote:

    Thanks for the help guys, I am slowing learning.

    With this advice ->

    >
    >There is no 'erase' member that takes a pointer to int. If your
    >implementation _happens_ to have vector::iterator the same as
    >a pointer to the contained type, it doesn't mean it will work
    >on any other computers/compilers/platforms. You have to pass
    >an iterator to 'erase'.
    >



    Would this be a safe way to erase an element from a vector?

    std::vector<CWindowKeeperWindow*>::iterator IVec;

    // for(UINT i=0;i<uiSize;i++)
    for(IVec=m_vecInstalledTimers.begin();
    IVec!=m_vecInstalledTimers.end();)
    if((*IVec)->get_window_id()==hTreeItem)
    {
    //
    m_vecInstalledTimers.erase(&m_vecInstalledTimers);
    IVec=m_vecInstalledTimers.erase(IVec);

    #ifdef __CWINDOWKEEPER_DEBUG__
    ConPrintf(_T("OnDeleteWindow() - erased timer
    element\n"));
    #endif
    }
    else
    ++IVec;
    }
    Sir_Ciph3r, Jul 31, 2003
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Heyes
    Replies:
    8
    Views:
    711
    Andrew Koenig
    Jan 15, 2006
  2. Replies:
    8
    Views:
    1,896
    Csaba
    Feb 18, 2006
  3. Replies:
    1
    Views:
    408
    red floyd
    Dec 21, 2008
  4. Thomas J. Gritzan
    Replies:
    6
    Views:
    999
    James Kanze
    Dec 22, 2008
  5. James Kanze
    Replies:
    0
    Views:
    1,983
    James Kanze
    Dec 21, 2008
Loading...

Share This Page