I do not quite understand what an instance of std::function
actually contains.
Is it more efficient to pass it by-value or by-reference?
What are the performance effects in the following examples?
by-value:
void printStats(std::function<void(const char *)> printer);
. . .
std::string tmp;
printStats([&tmp](const char * msg){ tmp += msg; });
by rvalue-reference:
void printStats(std::function<void(const char *)>&& printer);
. . .
std::string tmp;
printStats([&tmp](const char * msg){ tmp += msg; });
If there is any possibility you are storing a copy of the std::function , pass by value. Otherwise, either way is roughly equivalent: the only downside to by-value is if you are taking the same bulky std::function and having one sub method after another use it. Barring that, a move will be as efficient as a const& .
You can pass an object to a function that takes an rvalue reference unless the object is marked as const . The following example shows the function f , which is overloaded to take an lvalue reference and an rvalue reference. The main function calls f with both lvalues and an rvalue.
Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
First, std::function
is required to avoid allocation in the case where the target is a function pointer of std::reference_wrapper
; implementations are encouraged to avoid allocation for "small" targets:
[...] for example, where
f
's target is an object holding only a pointer or reference to an object and a member function pointer.
That means that copying a std::function
whose target is large will involve an allocation and a copy of the target (reference counting is not permitted, since the target might have mutable state). However, in your specific case the copy will be elided since you are calling your function with a prvalue temporary.
In your specific case, since you are calling the function immediately you don't need to worry about taking ownership of it, so it would be better to take the function by const reference. Taking it by rvalue reference would cause a headache to a user who has an existing lvalue or const reference to a function; they would need to std::move
it (in the former case) or create a prvalue temporary copy (in the latter case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With