Reputation: 6103
Why these definitions are all ok:
int func(int p=255) {
return p;
}
int func1(const int &p=255) {
return p;
}
but this definition:
int func2(int &p=255) {
return p;
}
leads to compile error ?
What is the logic behind it ?
Upvotes: 2
Views: 1339
Reputation: 172894
A non-const reference must be bound to lvalue (i.e. its address could be got). 255
(i.e. an int literal) is not a lvalue, so int &p=255
fails.
A const reference could be bound to rvalue, and for this case, a temporary int
will be created and initialized from 255
. The temporary int
's lifetime will be the same as the const reference.
Upvotes: 2
Reputation: 1499
int func(int p=255) {
return p;
}
p
here is copied by value, and it is defined to exist in the scope of func
.
int func2(int &p) {
return p;
}
// e.g. use:
int value = 10;
func2(value); // func2 *could* modify value because it is passed by non-const reference
In this case the compiler here expects p
to have a name somewhere in memory (i.e. lvalue), so it can possibly write to it within func2
. Passing by non-const reference allows you to modify the variable used in the function call. Since p
must belong to someone else somewhere since it can be modified, you can't assign a default value to it.
But what about the const-reference case? Here, the compiler is smart enough to know that p
can never be written to since it is const, so it doesn't need to have a name in memory to write to. In cases of a literal being passed (e.g. 255), it (behind the scenes) essentially creates a temporary and passes that temporary variable to the function.
int func1(const int &p=255) {
return p;
}
func1(10);
// Behind the scenes, the compiler creates something along these lines
// since it can never be modified.
const int some_temporary = 10;
func1(some_temporary);
Upvotes: 0
Reputation: 145239
The attempted function definition
auto func2( int& p = 255 )
-> int
{ return p; }
… fails because you can't bind an rvalue to a reference to non-const
. Basically that rule is because a simple value like 255
isn't modifiable. While the reference can be used to modify.
One simple solution is to express the default as a separate overload:
auto func2( int& p )
-> int
{ return p; }
auto func2()
-> int
{
int scratchpad = 255;
return func2( scratchpad );
}
Upvotes: 2
Reputation: 4265
Taking arguments by reference means, you dont work with your local copy of the variable, but with a variable already defined in the scope of the calling function.
While your first example makes sense (you have a local variable p that you can fill with a default value) the second example is a bit more tricky: Usually when using references you expect the variable to have an address, since you want to modify it. For const-refernces, the compiler will still allow you to pass a literal, even if something like "reference to a literal" makes no sense at all.
In the third case the compiler expects you to modify p. But what part of the memory should this modification affect? "255" has no address - therefore it cant be used as a reference.
If you want to have a more detailed explanation, you should probably look for keywords like "rvalue" and "lvalue".
Upvotes: 3