Ampersand inside casting
I come across this code
int n1 = 10;
int n2 = (int &)n1;
I don't understand the meaning of this casting, n2 is not reference since modifying n1 doesn't reflect n1. Strangely this co开发者_开发百科de throws compiler error in gcc where as compiles fine in VC++.
Anybody know the meaning of this casting?
This is perfectly valid C++ code, and does compile with g++ 4.4.1. It creates a temporary reference to n1 and then uses the value referred to by that reference to initialise n2.
This may be easier to see if expresed as a function:
void f( int & n1 ) {
int n2 = n1; // initialise with valuue referred to by n1
}
Note this is not valid C code, as C does not support references.
Assuming n2
is of some built-in type, the cast to int &
type performs the reinterpretation of lvalue n1
(whatever type it had) as an lvalue of type int
.
In the context of int n2 = (int &) n1
declaration, if n1
is by itself an lvalue of type int
, the cast is superfluous, it changes absolutely nothing. If n1
is an lvalue of type const int
, then the cast simply casts away the constness, which is also superfluous in the above context. If n1
is an lvalue of some other type, the cast simply reinterprets memory occupied by n1
as an object of type int
(this is called type punning). If n1
is not an lvalue the code is ill-formed.
So, in the code like int n2 = (int&) n1
the cast to int &
is only non-redundant (has some actual effect) when it does type punning, i.e when n1
is an lvalue of some other type (not int
). For example
float n1 = 5.0;
int n2 = (int &) n1;
which would be equivalent to
int n2 = *(int *) &n1;
and to
int n2 = *reinterpret_cast<int *>(&n1);
Needless to say, this is a pretty bad programming practice.
This is, BTW, one of the cases when using a dedicated C++-style cast is strongly preferred. If the author of the code used reinterpret_cast
instead of C-style cast, you probably wouldn't have to ask this question.
Of course, if n1
itself is of type int
, there's no meaningful explanation for this cast. In that case it is, again, completely superfluous.
P.S. There's also a possibility that n2
is a class with overloaded conversion operator to int &
type, which is a different story entirely... Anyway, you have to tell what n2
is when you ask questions like that.
int main()
{
int n1 = 10;
int n2 = (int &)n1;
cout<<n2<<endl;
}
Prints 10 as expected.
There is no problem with the cast.
It just creates a temporary reference as suggested by the next output:
int main()
{
int n1 = 10;
int n2 = (int &)n1;
n2 = 20;
cout<<n1<<endl; // print 10 and not 20.
}
I believe it's probably a typo in the original code.
GCC is usually more pedantic than VC++. However this code seems fine even though it's doing unnecessary things. Basically a temp reference is created for n1 and then the copy constructor is used to instantiate n2.
It does the obvious thing. Cast n1
to an int reference, and then assign it to the int n2
.
And assuming n1
is an int, it should compile just fine.
It won't compile if n1
is a rvalue. The following won't compile, for example:
(int&)foo();
(int&)42;
(int&) (x+y); // assuming x and y are int variables
It compiles in gcc too (I tried just to be sure). It simply casts n1 to a reference.
精彩评论