Ссылка как ключ в std :: map - PullRequest
13 голосов
/ 13 июля 2010

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

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

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

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

РЕДАКТИРОВАТЬ:

Это моё текущее решение ... но добавление итератора на карту - это УЖАСНО:

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

Ответы [ 4 ]

17 голосов
/ 13 июля 2010

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

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

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

11 голосов
/ 13 июля 2010

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

map <string,data> mymap;

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

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

struct data {
    std::string s;
    int i;
};
0 голосов
/ 13 июля 2010

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

0 голосов
/ 13 июля 2010

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

Но проверено на Microsoft STL.

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

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

...