2

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 ?

2
  • 2
    Because numeric literals aren't modifiable? Commented Feb 13, 2016 at 15:33
  • Why don't you add the compiler error message, for completeness? Commented Feb 13, 2016 at 15:44

4 Answers 4

3

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

Sign up to request clarification or add additional context in comments.

Comments

2

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 ); } 

1 Comment

Underrated response! The overload does exactly what one might possibly want to achieve with an optional non-const pass-by-reference!
2

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.

Comments

0
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); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.