I understand about the reference type with l-value that it should have address.
But, I don't understand why it works.
I think {1}
is r-value, but it works correctly..
void func(const vector<int>& v)
{
;
}
int main()
{
func({ 1 });
return 0;
}
{ 1 }
is not an expression at all. It doesn't have any value category or type.
Braces { /*...* }
in a function argument simply mean that the parameter shall be initialized as if by = { /*...*/ }
in a variable definition.
So all it means is that the initialization of the parameter will happen exactly as if you wrote
const vector<int>& v = { 1 };
And this works, because the initialization rules for const
lvalue references permit creating a temporary object to which the reference may be bound.
So this is (almost) equivalent to
const vector<int> unnamed = { 1 };
const vector<int>& v = unnamed;
where unnamed
is a temporary object without name and with lifetime extended until the end of the full-expression in which the function call happens.
I understand about the reference type with l-value that it should have address.
Every object in C++, even if it is a temporary object, has an address. It is not a good idea to think about lvalue references as something that can only bind to something with an address. A reference can always bind to any object of a compatible type. There is nothing about an object that makes it "lvalue" or "rvalue" or differentiating it by whether or not it has an address.
The rules about which value category an expression must have to be usable to initialize a reference are purely syntactical and in principle arbitrary language design decisions. And in particular the decision made for C++ is that a non-const
lvalue reference is not permitted to be initialized by an rvalue expression, while a const
lvalue reference may, even if that necessitates creating a temporary object to bind to.