Как я могу получить значение с карты?

У меня есть map с именем valueMap следующим образом:

typedef std::map<std::string, std::string>MAP;
MAP valueMap;
...
// Entering data.

Затем я передаю эту карту функции по ссылке:

void function(const MAP &map)
{
  std::string value = map["string"];
  // By doing so I am getting an error.
}

Как я могу получить значение из карты, которая передается как ссылка на функцию?


person Aneesh Narayanan    schedule 22.05.2012    source источник
comment
Когда вы публикуете сообщение об ошибке, вы всегда должны включать фактическую ошибку в вопрос.   -  person Some programmer dude    schedule 22.05.2012


Ответы (6)


К сожалению, std::map::operator[] не является константной функцией-членом, и у вас есть ссылка на константу.

Вам либо нужно изменить подпись function, либо сделать:

MAP::const_iterator pos = map.find("string");
if (pos == map.end()) {
    //handle the error
} else {
    std::string value = pos->second;
    ...
}

operator[] обрабатывает ошибку, добавляя на карту значение, созданное по умолчанию, и возвращая ссылку на него. Это бесполезно, когда все, что у вас есть, это ссылка на константу, поэтому вам нужно будет сделать что-то другое.

Вы можете проигнорировать эту возможность и написать string value = map.find("string")->second;, если логика вашей программы каким-то образом гарантирует, что "string" уже является ключом. Очевидная проблема заключается в том, что если вы ошибаетесь, вы получаете неопределенное поведение.

person Steve Jessop    schedule 22.05.2012
comment
используйте MAP::const_iterator вместо auto, если ваш компилятор еще не поддерживает auto. - person smerlin; 22.05.2012
comment
разве это не должно быть std::string value = pos->second; или const std::string& value = pos->second;? - person smerlin; 22.05.2012
comment
@smerlin: хорошая мысль, исправлено. Нужна ли вопрошающему копия значения или он может использовать константную ссылку, зависит от не показанного кода. Вот и решил не заморачиваться :-) - person Steve Jessop; 22.05.2012

map.at("key") выдает исключение, если отсутствует ключ

Если k не соответствует ключу какого-либо элемента в контейнере, функция генерирует исключение out_of_range.

http://www.cplusplus.com/reference/map/map/at/

person Gabe Rainbow    schedule 13.01.2014

ответ от Стива Джессопа хорошо объясняет, почему вы не можете использовать std::map::operator[] на const std::map. Гейб Рейнбоу ответ предлагает хорошую альтернативу. Я просто хотел бы предоставить пример кода, как использовать map::at() . Итак, вот расширенный пример вашего function():

void function(const MAP &map, const std::string &findMe) {
    try {
        const std::string& value = map.at(findMe);
        std::cout << "Value of key \"" << findMe.c_str() << "\": " << value.c_str() << std::endl;
        // TODO: Handle the element found.
    }
    catch (const std::out_of_range&) {
        std::cout << "Key \"" << findMe.c_str() << "\" not found" << std::endl;
        // TODO: Deal with the missing element.
    }
}

А вот пример функции main():

int main() {
    MAP valueMap;
    valueMap["string"] = "abc";
    function(valueMap, "string");
    function(valueMap, "strong");
    return 0;
}

Выход:

Значение ключа "string": abc
Ключ "strong" не найден

Код на Ideone

person honk    schedule 08.03.2019

Основная проблема заключается в том, что оператор [] используется для вставки и чтения значения в карту и из карты, поэтому он не может быть константой. Если ключ не существует, он создаст новую запись со значением по умолчанию, увеличивая размер карты, которая будет содержать новый ключ с пустой строкой, в данном конкретном случае, в качестве значения, если ключ существует еще не существует. Вы должны избегать operator[] при чтении с карты и использовать, как упоминалось ранее, "map.at(key)" для обеспечения проверки привязки. Это одна из самых распространенных ошибок, которую люди часто делают с картами. Вы должны использовать «insert» и «at», если ваш код не знает об этом факте. Прочтите этот доклад о распространенных ошибках Любопытно повторяющиеся ошибки C++ на Facebook

person Aitor    schedule 27.10.2019

Как я могу получить значение из карты, которая передается как ссылка на функцию?

Ну, вы можете передать это как ссылку. Стандартная обертка ссылок.

typedef std::map<std::string, std::string> MAP;
// create your map reference type
using map_ref_t = std::reference_wrapper<MAP>;

// use it 
void function(map_ref_t map_r)
{
    // get to the map from inside the
    // std::reference_wrapper
    // see the alternatives behind that link
    MAP & the_map = map_r;
    // take the value from the map
    // by reference
    auto & value_r = the_map["key"];
    // change it, "in place"
    value_r = "new!";
}

И тест.

    void test_ref_to_map() {

    MAP valueMap;
    valueMap["key"] = "value";
    // pass it by reference
    function(valueMap);
    // check that the value has changed
    assert( "new!" == valueMap["key"] );
}

Я думаю, что это красиво и просто. Наслаждаться ...

person Chef Gladiator    schedule 08.03.2019

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

template<class T1, class T2> class Bimap
{
std::map<T1, T2*> map1;
std::map<T2, T1*> map2;
public:
    void addRow(T1 &t1, T2 &t2){
        map1.insert(make_pair(t1, &t2));
        map2.insert(make_pair(t2, &t1));
    }
    T2* findForward(T1 t1){
        T2* value = map1.find(t1)->second;
        return value;
    }
    T1* findBackward(T2 t2){
        T1* value = map2.find(t2)->first;
        return value;
    }
};

Использование класса:

//Init mapp with int,int
Bimap<int,int> mapp;

//Add a row(Record) in bimap
int a = 5;
int b = 7002;
mapp.addRow(a, b);

//Print a record
int *ans= mapp.findForward(a);
cout<<"Bimap Returned:"<<*ans<<endl;
person Agent_Orange    schedule 09.05.2021