Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing functor object by value vs by reference (C++)

Tags:

c++

templates

Compare generic integration functions:

template <class F> double integrate(F integrand); 

with

template <class F> double integrate(F& integrand); 

or

template <class F> double integrate(const F& integrand); 

What are the pros and cons of each? STL uses the first approach (pass by value), does it mean it's the most universal one?

like image 965
quant_dev Avatar asked Nov 19 '11 18:11

quant_dev


2 Answers

Function objects usually should be small so I don't think that passing them by value will suffer from performance noticably (compare it to the work the function does in its body). If you pass by value, you can also gain from code analysis, because a by value parameter is local to the function and the optimizer may tell when and when not a load from a data member of the functor can be omitted.

If the functor is stateless, passing it as argument implies no cost at all - the padding byte that the functor takes doesn't have to have any particular value (in the Itanium Abi used by GCC at least). When using references, you always have to pass an address.

The last one (const T&) has the drawback that in C++03 that doesn't work for raw functions, because in C++03 the program is ill-formed if you try to apply const to a function type (and is an SFINAE case). More recent implementations instead ignore const when applied on function types.

The second one (T&) has the obvious drawback that you cannot pass temporary functors.

Long story short, I would generally pass them by value, unless I see a clear benefit in concrete cases.

like image 173
Johannes Schaub - litb Avatar answered Sep 18 '22 20:09

Johannes Schaub - litb


STL uses the first approach (pass by value)

Sure, the standard libraries pass iterators and functors by value. They are assumed (rightly or wrongly) to be cheap to copy, and this means that if you write an iterator or a functor that is expensive to copy, you might have to find a way to optimize that later.

But that is just for the purposes for which the standard libraries use functors - mostly they're predicates, although there are also things like std::transform. If you're integrating a function, that suggests some kind of mathematics libraries, in which case I suppose you might be much more likely to deal with functions that carry a lot of state. You could for example have a class representing nth order polynomials, with n+1 coefficients as non-static data members.

In that case, a const reference might be better. When using such a functor in standard algorithms like transform, you might wrap it in a little class that performs indirection through a pointer, to ensure that it remains cheap to copy.

Taking a non-const reference is potentially annoying to users, since it stops them passing in temporaries.

like image 41
Steve Jessop Avatar answered Sep 20 '22 20:09

Steve Jessop