Управление строковой памятью во время назначения хранится на карте - PullRequest
0 голосов
/ 20 июля 2009

У меня есть строка, и я хотел бы поместить ссылку на эту строку на карту.

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

Будет ли карта (на всех соответствующих платформах) по-прежнему ссылаться на m_tmp с новым значением?

В соответствии с фиктивной программой, приведенной ниже, адрес s не меняется (linux AS4, gcc 3.4). Эквивалентно ли управление памятью в этом отношении на разных платформах?

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

Ответы [ 3 ]

2 голосов
/ 20 июля 2009

Почему бы вам не сделать это вместо этого:

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

выглядит мне безопаснее.

1 голос
/ 20 июля 2009

Хотя адрес s не меняется (переменные не могут делать это в c ++), содержимое строки может измениться (например, указатель из s.c_str ()), поэтому будьте осторожны при игре с такими вещами .

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

Я бы посчитал такую ​​конструкцию очень опасной, я предполагаю, например, что вы ожидаете, что ключ будет искать сравнения, основанные на строке, а не на расположении строк (т. Е. Значения Пуитнера).

Однако, игнорируя ваш выбор ключа, то, что вы делаете со значением m_tmp, является безопасным и хорошо определенным (то есть изменение одного изменит другой, потому что есть обе «одинаковые» переменные), при условии, что «string m_tmp;» не выходит из области видимости (или иным образом удаляется), а затем вы пытаетесь получить к нему доступ через карту (поскольку она больше не ссылается на действительную память).

Например, следующее небезопасно.

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

Стоит также отметить, что вы можете сделать это наоборот, опять же при условии, что элемент, с которого вы получили ссылку, не будет удален (однако это единственный раз, когда std :: map разрешается делать недействительной ссылку или итератор) .

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
0 голосов
/ 20 июля 2009

Если вы не ограничены в типе, я бы порекомендовал заключить вашу строку в другой класс, а не делать строку, и напрямую, это будет незначительно, но даст вам возможность подробно прокомментировать причину изменчивости , в то же время делая код немного более понятным в отношении значения.

Черт возьми, сделай это классом ReassignableString с единственным членом, который является публичной строкой, если хочешь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...