... what the compiler actually does step by step ... for the second so that I can understand why the 2nd one is invalid.
let's try and understand firstwhat references actually mean – a reference is an alias for another variable (l-value), i.e. simplistically, one which has a memory address. In your program's second case, 0 is an r-value (no memory address) and hence there is nothing to refer to so to speak. One way you could make it work though is to declare a const reference:
constchar& p = 0;
now p can only be an alias (reference) for 0. If it were not const qualified p would have been able to change the value of the variable it refers to (as references usally can) which in the case of 0 would be meaningless
As regards the compiler code for the first example: https://godbolt.org/
# include <iostream>
int main()
{
char p = 'a';
char* q = &p;
char& r = p;
std::cout << "value of p: " << p << "\n";
std::cout << "memory address of p: " << &p << "\n\n";
std::cout << "value of object pointed to by q: " << *q << "\n";
std::cout << "value of q (aka memory address of p): " << q << "\n";
std::cout << "memory address of q (unrelated to p): " << &q << "\n\n";
std::cout << "value of r (aka value of p): " << r << "\n";
std::cout << "memory address of r (aka memory address of p and value of q): " << &r << "\n";
//std::cout << *r ; error: invalid type argument of unary '*'(have 'char')
}
Ok, why is the compiler like this , in tge second case the compiler can assign a memory to the literal and then make r tge alias but It doesn't. Is there any logical reason behind this?
in the second case note that r does not refer to the literal directly but through the (l-value) variable p, and therefore r can make changes to the value of p as it is a reference to p:
1 2 3 4 5 6 7 8 9
# include <iostream>
int main()
{
char p = 'a';
char& r = p;
r = 'b';
std::cout << p << "\n";
}
whereas in your OP example the reference was directly to 0 and to a variable that was assigned a value of 0
Sorry, I mean in char& r = 0 not your code. Here literal, the compiler could have assigned a memory for the literal and then make r an alias. I mean whats the logic behind this? Why does the compiler doesnt allow a literal to be referenced. Also what is the exact behaviour of a literal.
A literal cannot be modified. Access through a non-const reference allows modification. Therefore, access through a non-const reference is not allowed.
Rephrased:
A reference is an alias for a value or variable, and must match the type of the value or variable to which it refers. Literals are const. Therefore, references which refer to them must be of type reference-to-const.
they are supposed to be, and for the most part, are. If you really tried hard enough you might find a way to modify one, esp if you attacked it with assembler or a convoluted pointer chain. Once you did that, behavior becomes undefined, though you might manage to do nothing more than change the value. Its not something you would do, or want to do, in any sense of normal programming.