views:

290

answers:

6

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 code throws compiler error in gcc where as compiles fine in VC++.

Anybody know the meaning of this casting?

+10  A: 

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.

anon
I'd say that in this context it is only "prefectly" valid in situations when it is superfluous, i.e. when `n1` itself has type `int`. When it is non-superfluous, it is a `reinterpret_cast`. Usually when you need to reinterpret memory occupied by an another object, the resultant code might be syntactically valid, but far from perfect, so to say.
AndreyT
I must admit, I assumed n1 was an int. Unless the OP respomds though, we may never know....
anon
What's a "temporary reference"?
Pavel Minaev
A: 

It compiles in gcc too (I tried just to be sure). It simply casts n1 to a reference.

Andreas Bonini
+1  A: 

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.

ruibm
operator=, surely? And if so, you would be wrong. The code shows an initialisation, not an assignment - they are different things in C++.
anon
True, correcting reply.
ruibm
`n2` has type `int`. Type `int` is not a class type. It has no copy constructor. It has no constructors at all.
AndreyT
Another valid point. I guess the explanation above to all classes that aren't pod types in C++. For int, double, float would just do a normal assignment.
ruibm
+2  A: 
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.
}
codaddict
So how is this different than just "int n2 = n1"?
Graphics Noob
+1  A: 

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
jalf
AndreyT
True. Fixed now :)
jalf
+7  A: 

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.

AndreyT