Van Tr
Van Tr

Reputation: 6103

Why cannot assign value to non-const reference?

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

Answers (4)

songyuanyao
songyuanyao

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

pyj
pyj

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

Cheers and hth. - Alf
Cheers and hth. - Alf

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

Anedar
Anedar

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

Related Questions