Reputation: 23
I have function which takes 2 arguments, but one of these (map container) is passed to another function:
void myFunc(const std::map<std::string, int> &myMap, int num) {
int x = internalFunc(myMap);
// do some stuff...
}
int internalFunc(const std::map<std::string, int> &myMap) {
// return some map statistics
}
somewhere in main.cpp :
std::map<std::string, int> map1{ {"Hello", 10}, {"Hello2", 20}, {"Hello3", 30} };
myFunc(map1, 20);
My question is:
Is move semantics a good way for optimising this piece of code (passing one argument to another function using move) like this:
int internalFunc(std::map<std::string, int> &&myMap) {
// now gets rvalue reference
// return some map statistics
}
void myFunc(std::map<std::string, int> myMap, int num) {
int x = internalFunc(std::move(myMap));
// do some stuff...
}
I prefer not to use universal reference (using template) and std::forward in this case because this function is always called with this type of map and I prefer to keep the code as simple as possible.
internalFunc is always called by this one specific function myFunc.
Is move semantics good way for optimising this kind of functions? I understand that optimising using move semantics depends on moved object type, but let's stick to the example above with standard map container.
Thank you
Upvotes: 2
Views: 3856
Reputation: 3018
Move semantics are useful if you need to modify the map
or if the function needs to take ownership of the map
for some reason (maybe the latter is more understandable if the functions were class members, i.e. setters or constructors for instance).
You should use const std::map<std::string, int>&
for 3 main reasons:
map
won't be modified.move
semantics.Note on move semantics
If you use move semantics, the arguments of your functions don't necessarily need the double &&
. Generally, it is better to omit them (except for perfect forwarding and non-copyable objects like stream objects). The &&
requires that the passed arguments be rvalues
. However, omitting the &&
does not mean you cannot pass the arguments as rvalues
. Let's see this with an example:
int internalFunc(std::map<std::string, int> myMap)
{
/* ... */
return 1; // or whatever
}
void myFunc(std::map<std::string, int> myMap, int num)
{
int x = internalFunc(std::move(myMap));
// do some stuff...
}
The arguments myMap
in the above code don't get copied if you pass them as rvalues
:
int main()
{
myFunc({ {"Hello", 10}, {"Hello2", 20}, {"Hello3", 30} }, 20);
return 0;
}
Moreover, you can now use the same code by passing lvalues
, like you do in the main
function of your question (myFunc(map1, 20);
). The argument myMap
in myFunc
is then a copy of course. Also, your version with move semantics would not compile in this case.
If you really want to make sure the maps don't get copied, you can use the &&
, but this is rather rare, and, in my opinion, should be used only for objects which cannot be copied (i.e. stream objects).
Upvotes: 5