How to pass arguments effectively through many functions

From some time we can hear a lot that the meaning of semanthics is really important in C ++ (i.e. here and here ). I know that we should use it, especially when we intend to copy the value inside the function body anyway. Therefore, I assume that such use is true:

void foo(std::string txt) { my_container.emplace_back(move(txt)); } 

However, I did not find a recommendation on what to do if I need to pass this argument through a large function tree, which sometimes happens in a large project. For example:

 void bar(std::string txt) { foo(move(txt)); /* more actions */ } void boo(std::string txt) { bar(move(txt)); /* more actions */ } 

Can someone recommend what to do in this case? Should we stay with the semantics of value and hope that the compiler optimizer can limit the number of move operations or use const references around the world and only one copy at the end? Or maybe, like in many cases in C ++, it depends (for example, on copying and moving for a certain type) ?:-)

+8
c ++ c ++ 11
source share
2 answers

In general, it depends on the cost of copying and moving for a certain type (and even objects) and how it is called (with temporary or not, etc.)

For example, for temporary boo(gimme_t()) :

Let d be the depth of the tree of your classes

Solution with move cost d * COST_OF_MOVE , solution with COST_OF_COPY + d * REF_ASSIGNMENT .

You can see that for std::string it O(d) vs O(n) so for strings with a long length it is cheaper to use moves (and for short strings this is not so important), but for std::array<int> it's O(nd) vs O(n + d) , so you better use a single copy.

But if the argument is not temporary ( T t; boo(t) ), the costs will be:

COST_OF_COPY + d * COST_OF_MOVE vs COST_OF_COPY + d * REF_ASSIGNMENT , so the const-ref solution is faster by d .

But if you can consider move almost free ™, you better use a move solution to avoid 1 copy in case of a temporary argument


(*) Everywhere you have to read d ± 1 instead of d

+1
source share

For templates and template solutions, you obviously have to go with perfect forwarding. In other cases, a forced copy using the foo(MyType copy) declaration foo(MyType copy) seems like needles. Avoid overhead and copy when you need it, even if using copy-copy the compiler can be a little more efficient than move operations.

0
source share

All Articles