Home > Net >  function to returning reference of iterator of object
function to returning reference of iterator of object

Time:10-17

I would like to write a function to returning reference of iterator of an map entry in order to update the value of the entry. However, it fails at compile stage

#include <map>
#include <iostream>

using namespace std;

pair<int, string>& map_find(map<int,string>& m, int k){
    return *(m.find(k));
}

int main()
{
    map<int,string> m;
    
    // insert an entry
    m.insert(make_pair<int,string>(128490,"def"));
    
    // search entry by key
    auto e = map_find(m,128490);
    
    cout << e.first << e.second<<endl;;

    e.second = "abc"; // Update value
    
    // verify if the entry is updated
    e = map_find(m,128490);
    
    cout << e.first << e.second<<endl;;

    return 0;
}
main.cpp: In function ‘std::pair<int, std::__cxx11::basic_string<char> >& map_find(std::map<int, std::__cxx11::basic_string<char> >&, int)’:
main.cpp:15:12: error: invalid initialization of reference of type ‘std::pair >&’ from expression of type ‘std::pair >’
     return *(m.find(k));
            ^~~~~~~~~~~~

CodePudding user response:

The value type of std::map<Key, Value> is std::pair<const Key, Value>, not std::pair<Key, Value>. There are also useful member type aliases.

#include <map>
#include <iostream>

using MyMap = std::map<int, std::string>;

MyMap::reference map_find(MyMap& m, int k){
    return *(m.find(k));
}

int main()
{
    MyMap m;
    
    m.emplace(128490,"def");
    
    auto e = map_find(m,128490);
    
    std::cout << e.first << e.second << std::endl;

    // Does not update the string in the map, because e is a copy.   
    e.second = "abc";
    
    e = map_find(m,128490);
    
    std::cout << e.first << e.second << std::endl;

    return 0;
}

CodePudding user response:

In the class template std::map the value type is declared like

typedef pair<const Key, T> value_type;

As you can see the first template parameter has the qualifier const. And iterators of the class template return references to object of value_type.

So you need to write at least like

pair<const int, string>& map_find(map<int,string>& m, int k){
    return *m.find(k);
}

Otherwise you could change the key that would result in undefined behavior.

Pay attention to that the function is unsafe if the element with the given key is not found because in this case there will be an attempt to dereference the iterator that does not point to.an actual element.

Also instead of this statement

auto e = map_find(m,128490);

you need to write

auto &e = map_find(m,128490);
  •  Tags:  
  • c
  • Related