tags:

views:

212

answers:

4

I have a string and I would like to put a reference to that string into a map.

string m_tmp;
map<pair<string, string>, string&> m;
m[pair<string, string>("Foo","Bar")]= m_tmp;

then, I change the m_tmp;
m_tmp="DFDFD";

Will the map (on all conforming platforms) still reference m_tmp with a new value?

According to the dummy program below, the address of s does not change (linux AS4, gcc 3.4). Is the memory management in this regard equivalent across the platforms?

#include<string>
#include<iostream>

using namespace std;

int main()
{

   string s="Sasha";
   cout<<&s<<endl;  
   s="Bar";
   cout<<&s<<endl;  
   s="Foo";
   cout<<&s<<endl;  
}
+1  A: 

Although the address of s does not change (variables are not allowed to do that in c++), the contents of the string may change (eg the pointer from s.c_str()) so be careful when playing with stuff like that.

map<pair<const char*, const char*>, string&> m;

Id consider a construct like that very dangerous, I assume for example that you expect the key to look for comparisons based on the string, not the location of the strings (ie the poitner values).

However ignoring your choice of key, what your doing with the m_tmp value is safe and well defined (that is changing one will change the other, because there both the "same" variable), providing that the "string m_tmp;" does nto go out of scope (or otherwise deleted) and then you try to access it through the map (since it is no longer referencing valid memory).

Eg the following is not safe.

std::map<int, string &> myMap;
void foo()
{
    string s = "Hello World";
    myMap[5] = s;
}
int main()
{
    foo();
    //string s was destroyed when foo() returned, so myMap[5] is no longer a valid reference,
    //so it is not defined what will happen here, hopefully an access violation
    //rather than some obscure bug because the stack/heap got corrupted
    std::cout << myMap[5] << std::end;
}

Its also worth noting that you can do it the other way around, again providing that the element you got a reference from is not erased (however thats the only time an std::map is allowed to invalidate a reference or iterator).

std::map<int,string> myMap;
myMap[5] = "x";
string &s = myMap[5];//get a referecnce
myMap[5] = "Foo";
std::cout << s << std::end;//print Foo
s = "Bar";
std::cout << myMap[5] << std::endl;//print Bar
Fire Lancer
Well then as I said its safe, and changing one will change the other :)
Fire Lancer
+2  A: 

Why dont you do this instead:

map<pair<string, string>, shared_ptr<string> > m;

Looks safer to me.

Edouard A.
already changed to that
will this work btw: map<pair<string, string>, string > m;m[pair<string, string>("Foo","Bar") "string"]; ??I just noticed that: Why shared_ptr. looks like an overkill to me
shared_ptr reduces the number of copies of your object to one. It depends on your use case but it may not be required. Accessing will also be faster as you move around only a pointer, not a string object (with copies of the underlying chain). If your strings are short, this is probably overkill.
Edouard A.
You are using a reference to a string, so the assumption is you are optimising for memory performance. 95% of the time map<pair<string, string> string> is what one would use however, you're correct.
polyglot
I am using reference to ensure that my map gets updated when a reference is changed ...without having to update the map explicitly...
A: 

In the second code sample, the string address will not change. There's no facility to move within memory class instances once instantiated (though rvalue references may "sort of" change that.)

The object reference can be likened to a pointer address with a dereferenced syntax.

That is, the reference will be valid while the object is not deconstructed (either due to being on the stack, and the stack being unwound, or being in the heap, and delete being called upon it.)

The syntax to have the map value be a reference to a string is unusual and I have not seen it before, it certainly doesn't work under Microsoft C++ compilers as far as I know. I can't speak for GCC but I am surprised if that compiles.

polyglot
Hmm apparently not, although a map of pointers to string works, and is basicly the same thing considering references are generally implemented as pointers...
Fire Lancer
A: 

Unless you are restricted on the type, I would recommend wrapping your string in another class rather than doing a string& directly, there will be a tiny bit of overhead, but will give you a place to thoroughly comment the reason for the mutability, while also making the code a bit more obvious as to meaning.

Heck make it a class called ReassignableString with its only member a public string if you want.

Guvante