why an int pointer can hold the address of a const int? |
There is an int(x) somewhere in memory. The const modifier makes it so you cannot change x, it is a const int and this is enforced by the compiler. There is another location in memory (y) that stores the address of x. y is a pointer to const int, and the compiler respects this. There is another location z that stores the same address. It's just the address of an int, by using const_cast you have told the compiler to treat the storage as int. As far as the compiler is concerned, y is the address of a const int and x is the address of an int. They just happen to be at the same location at the same time.
1 2 3 4
|
int a = 10;
const int *b = &a;
a = 24;
// *b = 15; -> illegal
|
Even though, a is not const you cannot change it by using b. If a were const as below, then you cannot use a pointer to int, you have to use a pointer to const int.
1 2 3
|
const int a = 10;
// int *b = &a; -> illegal
// a = 24; -> illegal
|
I would find that the value of x didn't change |
Because x is a built-in type, simple enough for the compiler to hold it in it's symbol table, and fold it in. So the compiler knows x is a const, and uses that value everywhere you directly refer to x, so when running your program, x is not directly read from storage, it has been folded in at compile time. Of coursethis does not apply to the pointers.
If x were a more complex object then the results would be different. To prove that x has indeed changed, try this sort of thing to prove it, after line 10, add:
1 2
|
unsigned long cy = (unsigned long)(&x);
cout << hex << cy << ":" << *((int *) cy) << endl;
|
Or this contrived example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
#include <iostream>
using namespace std;
class X
{
public:
X(int r) : x(r) {}
X operator=(int r)
{
x = r;
return *this;
}
friend ostream &operator<<(ostream &os, const X& mx);
private:
int x;
};
ostream &operator<<(ostream &os, const X& mx) { return os << mx.x; }
int main()
{
const X x(3);
const X *y=&x;
X *z=const_cast<X*>(y);
cout<<x<<" "<<*y<<" "<<*z<<endl;
cout<<&x<<" "<<y<<" "<<z<<endl;
*z=4;
cout<<x<<" "<<*y<<" "<<*z<<endl;
cout<<&x<<" "<<y<<" "<<z<<endl;
}
|