Ссылка как ключ в std:: map

Предположим, что некоторая структура данных:

typedef struct {
    std::string s;
    int i;
} data;

Если я использую поле data.s в качестве ключа при добавлении экземпляров data в карту типа std::map<std::string&, data>, скопирует ли строка? Можно ли стереть элемент карты, потому что ссылка станет недействительной?

Также ответы на эти вопросы также относятся к unordered_map?

EDIT:

Это мое текущее решение... но добавление итератора к карте UGLY:

typedef struct {
    const std::string* s;
    int i;
} data;

std::map<std::string, data> map;
typedef std::map<std::string, data>::iterator iterator;

// add an element to the map
iterator add_element(const std::string& s) {
    std::pair<iterator, bool> p = states.insert(std::make_pair(s, data()));
    iterator i = p.first;
    if(p.second) {
        data& d = (*i).second;
        d.s = &(*i).first;
    }
    return i;
}

Ответ 1

Вы не можете хранить ссылки в контейнерах стандартной библиотеки - ваша карта должна выглядеть так:

map <string,data> mymap;

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

Обратите внимание, что в С++ вам не нужны typedefs для объявления структур:

struct data {
    std::string s;
    int i;
};

Ответ 2

Вы можете взглянуть на boost.ref. Он предоставляет оболочку, которая позволяет ссылаться на ссылки в STL-контейнерах следующим образом:

std::map<boost::reference_wrapper<std::string>, data>

Как и в С++ 11, это часть стандарта (до этого компиляторы, которые реализуют TR1, также предлагают его в пространстве имен std::tr1).

Ответ 3

Вы не можете использовать ссылку. Карта может скопировать содержимое. Вероятно, это зависит от реализации.

Но протестирован с microsoft STL.

struct data
{
            data(data const& rhs)
            {
               a new object will be created here
            }
            std::string s;
            int i; 
};

Добавьте некоторые объекты к карте, и вы запуститесь в конструктор копирования. Это должно аннулировать вашу ссылку.

Ответ 4

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