What is wrong with reference into std::map?

Discussion in 'C++' started by Jim Langston, May 14, 2006.

  1. Jim Langston

    Jim Langston Guest

    Expected output of program:
    Key is: 0 String is: Hello
    Key is: 1 String is: Goodbye
    Key is: 2 String is: The end

    Actual output:
    Key is: 0 String is: The End
    Key is: 1 String is:
    Key is: 2 String is:

    What am I doing wrong?

    If I declare my reference fresh each time, such as putting { } around the
    places I insert and doing
    std::string& MyString = (*it).second;
    each time it will come out right.

    Why can't I reuse the references?

    It took a long time to find out what was causing this in my program. This
    is just a test program showing the issue.

    #include <iostream>
    #include <string>
    #include <map>

    std::map<unsigned int, std::string> MyMap;

    int main ()
    {
    unsigned int ID = 0;
    std::map< unsigned int, std::string>::iterator it = MyMap.insert(
    MyMap.end(), std::make_pair< unsigned int, std::string >( ID,
    std::string() ) );
    std::string& MyString = (*it).second;
    MyString = "Hello";

    ID = 1;
    it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    std::string >( ID, std::string() ) );
    std::string& MyString2 = (*it).second;
    MyString = "Goodbye";

    ID = 2;
    it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    std::string >( ID, std::string() ) );
    MyString = (*it).second;
    MyString = "The End";

    for ( std::map< unsigned int, std::string >::iterator i = MyMap.begin();
    i != MyMap.end(); ++i )
    {
    std::cout << "Key is: " << (*i).first << " String is: " <<
    (*i).second << std::endl;
    }

    std::string wait;
    std::cin >> wait;
    }
    Jim Langston, May 14, 2006
    #1
    1. Advertising

  2. Jim Langston

    Jim Langston Guest

    "Jim Langston" <> wrote in message
    news:TBK9g.30$...
    > Expected output of program:
    > Key is: 0 String is: Hello
    > Key is: 1 String is: Goodbye
    > Key is: 2 String is: The end
    >
    > Actual output:
    > Key is: 0 String is: The End
    > Key is: 1 String is:
    > Key is: 2 String is:
    >
    > What am I doing wrong?
    >
    > If I declare my reference fresh each time, such as putting { } around the
    > places I insert and doing
    > std::string& MyString = (*it).second;
    > each time it will come out right.
    >
    > Why can't I reuse the references?
    >
    > It took a long time to find out what was causing this in my program. This
    > is just a test program showing the issue.
    >
    > #include <iostream>
    > #include <string>
    > #include <map>
    >
    > std::map<unsigned int, std::string> MyMap;
    >
    > int main ()
    > {
    > unsigned int ID = 0;
    > std::map< unsigned int, std::string>::iterator it = MyMap.insert(
    > MyMap.end(), std::make_pair< unsigned int, std::string >( ID,
    > std::string() ) );
    > std::string& MyString = (*it).second;
    > MyString = "Hello";
    >
    > ID = 1;
    > it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    > std::string >( ID, std::string() ) );
    > std::string& MyString2 = (*it).second;


    This was a broken attempt to diagnose. Even with this line changed to:
    std::string& MyString2 = (*it).second

    the output is the same.

    > MyString = "Goodbye";
    >
    > ID = 2;
    > it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    > std::string >( ID, std::string() ) );
    > MyString = (*it).second;
    > MyString = "The End";
    >
    > for ( std::map< unsigned int, std::string >::iterator i =
    > MyMap.begin(); i != MyMap.end(); ++i )
    > {
    > std::cout << "Key is: " << (*i).first << " String is: " <<
    > (*i).second << std::endl;
    > }
    >
    > std::string wait;
    > std::cin >> wait;
    Jim Langston, May 14, 2006
    #2
    1. Advertising

  3. Jim Langston

    Ron Natalie Guest

    Jim Langston wrote:

    > std::string& MyString2 = (*it).second;
    > MyString = "Goodbye";


    You're going to kick yourself, but you want MyString2 in
    the above line. You're righting into the first inserted
    string here.
    >
    > ID = 2;
    > it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    > std::string >( ID, std::string() ) );
    > MyString = (*it).second;


    This doesn't initialize a reference, it assigns the value of second
    into where MyString was initialized (your first insertion).

    > MyString = "The End";


    And this does another such assignment

    >
    >
    >
    Ron Natalie, May 14, 2006
    #3
  4. Jim Langston

    Jim Langston Guest

    "Ron Natalie" <> wrote in message
    news:...
    > Jim Langston wrote:
    >
    >> std::string& MyString2 = (*it).second;
    >> MyString = "Goodbye";

    >
    > You're going to kick yourself, but you want MyString2 in
    > the above line. You're righting into the first inserted
    > string here.
    >>
    >> ID = 2;
    >> it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    >> std::string >( ID, std::string() ) );
    >> MyString = (*it).second;

    >
    > This doesn't initialize a reference, it assigns the value of second
    > into where MyString was initialized (your first insertion).


    Oh, well, shoot. You're right. That totally excaped me. If the reference
    is declared on the same line, then it initializes it.

    Hmm.. so how do you assign a reference that has already been initialized?
    I.E.
    int int1;
    int int2;
    int& MyRef = int1;
    Who do I do to get MyRef to point to int2 now? Or can I?

    >
    >> MyString = "The End";

    >
    > And this does another such assignment
    >
    >>
    >>
    Jim Langston, May 14, 2006
    #4
  5. Jim Langston

    Phlip Guest

    Jim Langston wrote:

    >>> it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    >>> std::string >( ID, std::string() ) );


    Could you break up all these long lines, pleeeeze? Start with

    typedef std::make_pair< unsigned int, std::string > mapType;

    then use that everywhere you copied in that whole gizmo.

    > Hmm.. so how do you assign a reference that has already been initialized?


    > int& MyRef = int1;
    > Who do I do to get MyRef to point to int2 now? Or can I?


    You can't reseat a reference. That's a feature. You said "point to", which
    betrays you think of a reference as a kind of pointer. It's really another
    name for something; an alias.

    Will a map let you use iterators? Some containers invalidate their iterators
    after an insert, but I can't think of a technical reason for a binary tree
    to do that, and maps generally implement as binary trees.

    --
    Phlip
    http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
    Phlip, May 14, 2006
    #5
  6. Jim Langston

    Jim Langston Guest

    "Phlip" <> wrote in message
    news:yTK9g.6118$...
    > Jim Langston wrote:
    >
    >>>> it = MyMap.insert( MyMap.end(), std::make_pair< unsigned int,
    >>>> std::string >( ID, std::string() ) );

    >
    > Could you break up all these long lines, pleeeeze? Start with
    >
    > typedef std::make_pair< unsigned int, std::string > mapType;
    >
    > then use that everywhere you copied in that whole gizmo.


    Yeah, well, the problem is I'm using a number of maps, 4, and I would have
    to do that for every map since they're different pair types. By the time I
    typedefed the maps, the iterators and the make pairs that's 12 different
    things I have to remember what is what.

    It's just easier for me to type them in so I don't have to keep going back
    and seeing what they are.

    >> Hmm.. so how do you assign a reference that has already been initialized?

    >
    >> int& MyRef = int1;
    >> Who do I do to get MyRef to point to int2 now? Or can I?

    >
    > You can't reseat a reference. That's a feature. You said "point to", which
    > betrays you think of a reference as a kind of pointer. It's really another
    > name for something; an alias.
    >
    > Will a map let you use iterators? Some containers invalidate their
    > iterators after an insert, but I can't think of a technical reason for a
    > binary tree to do that, and maps generally implement as binary trees.


    Well, I'm only using the reference after the insert to set the data, then I
    don't use it anymore. The reference may be invalidated after another
    insert, I'm not sure.

    Well, I came across this problem and figured out that by putting brackets
    around the whole thing the problem went away, I just wanted to know what the
    problem was before I converted it into a function.

    I'm goign to have to remember that you can't reset a reference. Dang, I
    hope they add that to the language. Even if it takes another keyword.

    std::reseat MyRef = int2;
    MyRef<std::reseat> = int2;
    std::reseat<int&>( MyRef ) = int2;

    any format



    >
    > --
    > Phlip
    > http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
    >
    Jim Langston, May 14, 2006
    #6
  7. Jim Langston wrote:
    > Well, I came across this problem and figured out that by putting brackets
    > around the whole thing the problem went away, I just wanted to know what the
    > problem was before I converted it into a function.

    You're not reseting the reference in this case, you're just creating a
    new one with new initialization

    > I'm goign to have to remember that you can't reset a reference. Dang, I
    > hope they add that to the language. Even if it takes another keyword.

    The language already has this, it's called a pointer :)

    > std::reseat MyRef = int2;
    > MyRef<std::reseat> = int2;
    > std::reseat<int&>( MyRef ) = int2;


    int *pPointer = &int2;
    *pPointer = 5;
    pPointer = int3; // Reseting the pointer

    Abdo Haji-Ali
    Programmer
    In|Framez
    Abdo Haji-Ali, May 14, 2006
    #7
  8. Jim Langston

    Jim Langston Guest

    "Abdo Haji-Ali" <> wrote in message
    news:...
    >
    > Jim Langston wrote:
    >> Well, I came across this problem and figured out that by putting brackets
    >> around the whole thing the problem went away, I just wanted to know what
    >> the
    >> problem was before I converted it into a function.

    > You're not reseting the reference in this case, you're just creating a
    > new one with new initialization
    >
    >> I'm goign to have to remember that you can't reset a reference. Dang, I
    >> hope they add that to the language. Even if it takes another keyword.

    > The language already has this, it's called a pointer :)
    >
    >> std::reseat MyRef = int2;
    >> MyRef<std::reseat> = int2;
    >> std::reseat<int&>( MyRef ) = int2;

    >
    > int *pPointer = &int2;
    > *pPointer = 5;
    > pPointer = int3; // Reseting the pointer


    Well, yes, I know how to reset pointers. I've been using pointers from my C
    days. But I now prefer references.
    Jim Langston, May 14, 2006
    #8
  9. Jim Langston

    Phlip Guest

    Jim Langston wrote:

    >> Could you break up all these long lines, pleeeeze? Start with
    >>
    >> typedef std::make_pair< unsigned int, std::string > mapType;
    >>
    >> then use that everywhere you copied in that whole gizmo.

    >
    > Yeah, well, the problem is I'm using a number of maps, 4, and I would have
    > to do that for every map since they're different pair types. By the time
    > I typedefed the maps, the iterators and the make pairs that's 12 different
    > things I have to remember what is what.


    That sounds like an argument _for_ typedeffing.

    > It's just easier for me to type them in so I don't have to keep going back
    > and seeing what they are.


    Give them stupid names, like map_int_string. Nobody said the names had to
    reveal their logical intent.

    (Actually, someone _did_ say that. Skip that rule for now!)

    > I'm goign to have to remember that you can't reset a reference. Dang, I
    > hope they add that to the language. Even if it takes another keyword.
    >
    > std::reseat MyRef = int2;
    > MyRef<std::reseat> = int2;
    > std::reseat<int&>( MyRef ) = int2;


    What's the point? Just use a pointer if you need the ability to re-seat.

    That's why you should prefer references to pointers unless you need
    pointers' extra abilities. Adding such abilities to pointers would dilute
    their effectiveness as the _weakest_ kind of handle we have.

    --
    Phlip
    http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
    Phlip, May 14, 2006
    #9
  10. Jim Langston <> wrote:

    > Well, yes, I know how to reset pointers. I've been using pointers
    > from my C days. But I now prefer references.


    Better use pointers when they are appropriate and do not
    dogmatically
    stick to references. If you want to reseat, then pointers _are_
    appropriate.

    If you need reseating functionality here is a different matter. I
    have
    not looked closely at the code to advise on that.

    (sorry I accidently replied to your email at first)

    regards
    --
    jb

    (reply address in rot13, unscramble first)
    Jakob Bieling, May 14, 2006
    #10
  11. In message <yTK9g.6118$>, Phlip
    <> writes
    >
    >Will a map let you use iterators? Some containers invalidate their iterators
    >after an insert, but I can't think of a technical reason for a binary tree
    >to do that, and maps generally implement as binary trees.
    >

    True, but irrelevant since it's not guaranteed by the standard. The
    following is:

    23.1.2/8. The insert members shall not affect the validity of iterators
    and references to the [associative] container, and the erase members
    shall invalidate only iterators and references to the erased elements.


    --
    Richard Herring
    Richard Herring, May 15, 2006
    #11
    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. Peter Jansson
    Replies:
    5
    Views:
    6,275
    Ivan Vecerina
    Mar 17, 2005
  2. Replies:
    1
    Views:
    409
    red floyd
    Dec 21, 2008
  3. Thomas J. Gritzan
    Replies:
    6
    Views:
    1,000
    James Kanze
    Dec 22, 2008
  4. James Kanze
    Replies:
    0
    Views:
    1,984
    James Kanze
    Dec 21, 2008
  5. Ian Collins
    Replies:
    3
    Views:
    957
    Thomas Beckmann
    Jan 19, 2009
Loading...

Share This Page