469,299 Members | 2,081 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,299 developers. It's quick & easy.

What is wrong with reference into std::map?

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


May 14 '06 #1
10 2219

"Jim Langston" <ta*******@rocketmail.com> wrote in message
news:TB*************@fe04.lga...
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;

May 14 '06 #2
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


May 14 '06 #3

"Ron Natalie" <ro*@spamcop.net> wrote in message
news:44**************@spamcop.net...
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


May 14 '06 #4
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!!!
May 14 '06 #5

"Phlip" <ph******@yahoo.com> wrote in message
news:yT*****************@newssvr27.news.prodigy.ne t...
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!!!

May 14 '06 #6

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

May 14 '06 #7

"Abdo Haji-Ali" <ah***@inframez.com> wrote in message
news:11**********************@j33g2000cwa.googlegr oups.com...

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.
May 14 '06 #8
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!!!
May 14 '06 #9
Jim Langston <ta*******@rocketmail.com> 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)
May 14 '06 #10
In message <yT*****************@newssvr27.news.prodigy.net> , Phlip
<ph******@yahoo.com> 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
May 15 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Christopher | last post: by
24 posts views Thread by Duane Hebert | last post: by
2 posts views Thread by ash | last post: by
44 posts views Thread by jmoy | last post: by
13 posts views Thread by kamaraj80 | last post: by
4 posts views Thread by Evyn | last post: by
7 posts views Thread by DevNull | last post: by
8 posts views Thread by mveygman | last post: by
reply views Thread by suresh191 | last post: by
reply views Thread by harlem98 | last post: by
1 post views Thread by Geralt96 | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.