why function objects should be pass-by-value
In a typical case, a function object will have little or (more often) no persistent state. In such a case, passing by value may no require actually passing anything at all -- the "value" that's passed is basically little or nothing more than a placeholder for "this is the object".
Given the small amount of code in many function objects, that leads to a further optimization: it's often fairly easy for the compiler to expand the code for the function object inline, so no parameters get passed, and no function call is involved at all.
A compiler may be able to do the same when you pass a pointer or reference instead, but it's not quite as easy -- a lot more common that you'll end up with an object being created, its address passed, and then the function call operator for that object being invoked via that pointer.
Edit: It's probably also worth mentioning that the same applies to lambdas, since they're really just function objects in disguise. You don't know the name of the class, but they create a class in the immediately surrounding scope that overloads the function call operator, which is what gets invoked when you "call" the lambda. [Thanks @Mark Garcia.]
Should I pass function objects by value or by reference?
TL;DR: You should use F: Fn() -> ()
or impl Fn() -> ()
as an argument.
Fn
As @Bubletan mentioned in their answer, the key point is that Fn
is automatically implemented for &F
if F
implements Fn
:
impl<'_, A, F> Fn<A> for &'_ F
where
F: Fn<A> + ?Sized,
The consequence is that:
foo(f: impl Fn() -> ())
can be called both withfoo(callable)
orfoo(&callable)
.foo(f: &impl Fn() -> ())
forces the caller to usefoo(&callable)
and disallowfoo(callable)
.
In general, it is best to leave the choice to the caller when there is downside for the callee, and therefore the first form should be preferred.
FnMut
The same logic applies to FnMut
, which is also automatically implemented for &mut F
if F
implements FnMut
:
impl<'_, A, F> FnMut<A> for &'_ mut F
where
F: FnMut<A> + ?Sized,
Which should therefore also be passed by value in arguments, leaving the choice to the caller as to whether they prefer foo(callable)
or foo(&mut callable)
.
FnOnce
There is the argument of consistency with FnOnce
, which can only be passed by value, which again points into the direction of taking arguments of the Fn*
family by value.
Does C++ pass objects by value or reference?
Arguments are passed by value, unless the function signature specifies otherwise:
- in
void foo(type arg)
,arg
is passed by value regardless of whethertype
is a simple type, a pointer type or a class type, - in
void foo(type& arg)
,arg
is passed by reference.
In case of arrays, the value that is passed is a pointer to the first element of the array. If you know the size of the array at compile time, you can pass an array by reference as well: void foo(type (&arg)[10])
.
Is it ok to pass function objects by reference?
Passing function objects by reference is fine, but you should be aware that many C++ algorithms copy function objects, so if you need a library algorithm to respect your state you should pass it as a reference inside your function object:
struct State {
double a, b, x, y;
};
struct Function {
State &state;
explicit Function(State &state): state(state) {}
double operator() (int v, int w) {....}
};
State state;
std::...(..., Function(state), ...)
Also, some library algorithms (e.g. transform
) require pre-C++11 that the function object have no side effects i.e. no state whatsoever; this requirement is rarely enforced and is relaxed in C++11.
C++: Reasons for passing objects by value
ALWAYS use pointers when using objects as arguments
No, in C++ always pass by reference, unless your function can be called with nullptr
as a valid argument. If the function does not need to modify the argument, pass by const
reference.
Passing arguments by value has several uses.
If your function needs to create a copy of the argument it is better to create this copy by passing by value rather than creating a copy within the function. For instance:
void foo( widget const& w )
{
widget temp( w );
// do something with temp
}
Instead use
void foo( widget w ) // copy is made here
{
// operate on w itself
}
Doing this also has the benefit of allowing the compiler to move widget
if possible, which is generally more efficient than creating copies.
can somebody explain me what does passing by value and Passing by reference mean in C#?
In simple terms...
"Passing by value" means that you pass the actual value of the variable into the function. So, in your example, it would pass the value 9.
"Passing by reference" means that you pass the variable itself into the function (not just the value). So, in your example, it would pass an integer object with the value of 9.
This has various consequences, and each is useful in different situations.
This answer has more thorough information:
What's the difference between passing by reference vs. passing by value?
Advantages of pass-by-value and std::move over pass-by-reference
- Did I understand correctly what is happening here?
Yes.
- Is there any upside of using
std::move
over passing by reference and just callingm_name{name}
?
An easy to grasp function signature without any additional overloads. The signature immediately reveals that the argument will be copied - this saves callers from wondering whether a const std::string&
reference might be stored as a data member, possibly becoming a dangling reference later on. And there is no need to overload on std::string&& name
and const std::string&
arguments to avoid unnecessary copies when rvalues are passed to the function. Passing an lvalue
std::string nameString("Alex");
Creature c(nameString);
to the function that takes its argument by value causes one copy and one move construction. Passing an rvalue to the same function
std::string nameString("Alex");
Creature c(std::move(nameString));
causes two move constructions. In contrast, when the function parameter is const std::string&
, there will always be a copy, even when passing an rvalue argument. This is clearly an advantage as long as the argument type is cheap to move-construct (this is the case for std::string
).
But there is a downside to consider: the reasoning doesn't work for functions that assign the function argument to another variable (instead of initializing it):
void setName(std::string name)
{
m_name = std::move(name);
}
will cause a deallocation of the resource that m_name
refers to before it's reassigned. I recommend reading Item 41 in Effective Modern C++ and also this question.
Where should I prefer pass-by-reference or pass-by-value?
There are four main cases where you should use pass-by-reference over pass-by-value:
- If you are calling a function that needs to modify its arguments, use pass-by-reference or pass-by-pointer. Otherwise, you’ll get a copy of the argument.
- If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.
- If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
- If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.
Related Topics
Creating a String List and an Enum List from a C++ MACro
Why Define Operator + or += Outside a Class, and How to Do It Properly
Load Shared Library by Path at Runtime
Compile Program for 32Bit on 64Bit Linux Os Causes Fatal Error
C++ Unified Assignment Operator Move-Semantics
Does C++11, 14, 17 or 20 Introduce a Standard Constant for Pi
Is There a Null Std::Ostream Implementation in C++ or Libraries
Print Template Typename at Compile Time
Portability of Native C++ Properties
How to Speed Up Floating-Point to Integer Number Conversion
C++: How to Check If the Cin Buffer Is Empty
C++ Specialization of Template Function Inside Template Class
Get Local Ip-Address Using Boost.Asio
How to Change an Executable's Properties? (Windows)