Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid taking a value copy when creating a map element

Tags:

c++

I have a std::map<std::string, std::vector<double>> foo, the contents of which I build up slowly using a function

bar(
    std::string key   /*key name*/,
    std::size_t index /*element index of the vector*/,
    double value      /*value to put in the vector at that index*/
)

This function populates foo in a way that I trust is obvious from the function parameter types and those brief comments.

However, I'm concerned that when I'm adding a new key, which happens when I do this

auto it = foo.find(index);
if (it == foo.end()){
   /*ToDo - avoid taking a vector value copy*/

I end up creating a new std::vector<double>, and putting that in a map. And that results in my taking a value copy of that vector. Is there a way (other than using smart pointers as map values) of doing this without taking a value copy?

like image 372
P45 Imminent Avatar asked Nov 30 '25 06:11

P45 Imminent


1 Answers

There has been a good way since C++11 (which, given your use of auto, you're using). This standard allows a special type of insertion called emplacement. The easiest way for you to exploit this would be to use

it = foo.emplace(
    std::make_pair(key, std::vector<double>(1 + index, 0.0/*a default value*/))
).first;

and then call it->second.at(index) = value which is something that you probably do anyway if find does return an element.

The emplacement technique is exploiting the move constructors of the anonymous temporary std::vector and the anonymous temporary std::pair. (Those temporaries are called r-value references).

For more details see http://en.cppreference.com/w/cpp/container/map/emplace

like image 91
Bathsheba Avatar answered Dec 01 '25 19:12

Bathsheba