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
#include <iostream>
struct B {
~B() {
std::cout << "~B" << std::endl;
}
};
struct A { int i; B b; };
int main() {
A *a = &(A){0};
std::cout << "main" << std::endl;
}
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").
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With