Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I pass std::function by-value or by (rvalue)-reference?

Tags:

c++

c++11

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; });
like image 567
rustyx Avatar asked Apr 01 '16 11:04

rustyx


People also ask

Should std :: function be passed by reference or value?

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& .

Can you pass an rvalue by reference?

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.

What is the point of std :: function?

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.

What are Rvalue references?

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.


1 Answers

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).

like image 165
ecatmur Avatar answered Nov 15 '22 13:11

ecatmur