I don’t understand how the following code compiles/doesn’t compile:
struct Temp
{
int i;
};
int main(int argc, char * argv[])
{
//Temp &ref1 = (Temp){42}; // Error, as expected
Temp &ref2 = *(Temp*)&(Temp){42}; // A-OK
std::cerr << ref2.i << std::endl;
return 0;
}
I’m using g++ 4.4.4.
Your code is not really C++. It uses a compound literal which is a C99 feature. In C99 it evaluates to an lvalue and taking the address of the literal is completely fine there. Integrating this extension into C++, GCC appears to change the rule of it and make it an rvalue, better fitting the classification of them into the existing rules of C++ for usual casts that also produce rvalues.
GCC does not like
&(Temp){42}, complaining that I take the address of a temporary. It’s a warning about invalid code which it still accepts but does not really like. The same warning is given for other obviously-wrong code like&A(), which is a legal functional style C++ cast, which also produces an rvalue and thus cannot be used as the operand of the address-of operator.The integration of compound literals into C++ by GCC also destroys the temporary prematurely, as can be seen by the following test
In C99, the object that the literal refers to will be alive for the entire block (it will have automatic storage duration). In GNU C++ the object is destructed already at the end of the full expression, before the end of its block is even reached (the “~B” is printed before the “main”).