Reputation: 10459
I was working on some template code this morning where I used a BOOST_STATIC_ASSERT
to ensure I wasn't creating a reference to the wrong type, as I thought it might be a clearer error message. However when I tried removing the static assert to take a look at the alternative compiler error I was shocked to discover that gcc doesn't even complain when you try to make a const double& referring to an int:
#include <iostream>
int main()
{
int x = 5;
const double& y = x;
std::cout << y << std::endl;
return 0;
}
Compiles, and doesn't even warn:
$ g++ ~/stuff/badRef.cpp -Wall -Wextra -pedantic
$ a.out
5
What's going on here? Is this undefined behaviour? If so why doesn't gcc complain? On my machine int is 4 bytes and a double is 8. That means that when printing a double& it should interpret 8 bytes at that address as a double and print it, yet there is actually a 4 byte int at that location.
Very confused. Help!
Upvotes: 18
Views: 4486
Reputation: 62975
const double& y = x;
creates a temporary double
with the value static_cast<double>(x)
, then binds that temporary to y
. The lifetime of the temporary is extended to match the lifetime of y
.
This is completely legal C++ (03 and 11), hence the lack of warning/error.
Upvotes: 23
Reputation: 54971
const T&
can bind to a temporary, so x
is being converted to double
and the copy is bound to y
. If you check, you’ll see that &x != &y
. The reason for this behaviour is to allow passing literals to functions that take their parameters by const
reference.
Upvotes: 2
Reputation: 104698
it's well defined and legal. y
refers to a temporary. consider also when you pass parameters:
void foo(const int& p);
foo(3.14);
Note also that this is not valid C++ if the reference is not const. VS 6 got that wrong and allowed binding a mutable reference to a temporary. This applies only to const references.
Upvotes: 11
Reputation: 27028
This is a good example for those who think that pointers and references are the same.
double const*const y2 = &x;
gives
bad.cpp:7:30: error: cannot convert ‘int*’ to ‘const double* const’ in initialization
The reason it works for references is explained in the other posts.
Upvotes: 1