Alex Cornford Alex Cornford - 4 months ago 45
C++ Question

C++ unordered_map, efficient lazy load and use of value

I want to use lazy loading of an unordered_map. I search the map for a key. If it exists I use the value. If it doesn't exist I create the value and emplace the key,value pair.

I want to avoid the last map.find() statement - it should be an unnecessary operation (performance is important). It might fail :-( and I'd hope for a better solution.

Note: The calling routine should only have a const reference to value. Avoid instantiation of value in calling routine.

How can I avoid the second lookup AND have a properly scoped const reference returned to the caller ?

h file

` typedef std::vector DataPtrListVector;
struct DataCacheStruct
DataPtrListVector dataItemOne;
typedef boost::unordered_map DataCacheMap;
// declare instance variable
DataCacheMap dataCacheMap;
// declare function
const DataCacheStruct& getOrCreateData( const std::string& dataKey,... );`

cpp file

` // Lazy Load of DataStruct unordered_map
std::string key = someString;
const DataCacheStruct& dataStruct = getOrCreateData( key, ... );

const DataCacheStruct& class::getOrCreateData( const std::string key, ...)
DataCacheMap::const_iterator itData = dataCacheMap.find(key);
if (itData != dataCacheMap.end())
return itData->second;
DataCacheStruct newData = doSomethingSlow();
dataCacheMap.emplace(std::make_pair(key, newData));
// Now I want to return newData as a const reference, as per unordered_map
// but it goes out of scope before the calling routine can use it.
DataCacheMap::const_iterator itData = dataCacheMap.find(key);
return itData->second;


As I've already said, the method emplace, returns a pair of an iterator to the newly inserted element and a value of true.

You can simply use that iterator, to get a reference:

auto it_new_insertion = dataCacheMap.emplace(std::make_pair(key, newData));
if (it_new_insertion.second == false) {  
 // something wrong with memory. handle it
return it_new_insertion.first->second;