Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it wise to use a pointer to access values in an std::map

Is it dangerous to returning a pointer out of a std::map::find to the data and using that as opposed to getting a copy of the data?

Currently, i get a pointer to an entry in my map and pass it to another function to display the data. I'm concerned about items moving causing the pointer to become invalid. Is this a legit concern?

Here is my sample function:

MyStruct* StructManagementClass::GetStructPtr(int structId)

{
    std::map<int, MyStruct>::iterator foundStruct;
    foundStruct= myStructList.find(structId);
    if (foundStruct== myStructList.end())
    {
        MyStruct newStruct;
        memset(&newStruct, 0, sizeof(MyStruct));
        myStructList.structId= structId;
        myStructList.insert(pair<int, MyStruct>(structId, newStruct));

       foundStruct= myStructList.find(structId);
   }

   return (MyStruct*) &foundStruct->second;

}

like image 456
Jason Avatar asked May 08 '13 14:05

Jason


2 Answers

It would undoubtedly be more typical to return an iterator than a pointer, though it probably makes little difference.

As far as remaining valid goes: a map iterator remains valid until/unless the item it refers to is removed/erased from the map.

When you insert or delete some other node in the map, that can result in the nodes in the map being rearranged. That's done by manipulating the pointers between the nodes though, so it changes what other nodes contain pointers to the node you care about, but does not change the address or content of that particular node, so pointers/iterators to that node remain valid.

like image 130
Jerry Coffin Avatar answered Sep 17 '22 18:09

Jerry Coffin


As long as you, your code, and your development team understand the lifetime of std::map values ( valid after insert, and invalid after erase, clear, assign, or operator= ), then using an iterator, const_iterator, ::mapped_type*, or ::mapped_type const* are all valid. Also, if the return is always guaranteed to exist, then ::mapped_type&, or ::mapped_type const& are also valid.

As for wise, I'd prefer the const versions over the mutable versions, and I'd prefer references over pointers over iterators.

Returning an iterator vs. a pointer is bad:

  • it exposes an implementation detail.
  • it is awkward to use, as the caller has to know to dereference the iterator, that the result is an std::pair, and that one must then call .second to get the actual value.
    • .first is the key that the user may not care about.
  • determining if an iterator is invalid requires knowledge of ::end(), which is not obviously available to the caller.
like image 21
Charles L Wilcox Avatar answered Sep 20 '22 18:09

Charles L Wilcox