Search code examples
c++inheritanceconstantsconst-cast

Why I am able to modify const variable through classes and not in plain code. C++


When I write this code fragment, after modifying the value of const variable i through pointer I am getting value of i as 10, but when i print *ptr i get 110.

const int i = 10;
int *ptr = const_cast<int *>(&i);
*ptr = *ptr + 100;
cout << "i:     " << i << "\t*ptr:      " << *ptr << endl;

I am getting output i: 10 and *ptr :110.

And in this case I am having a const variable x as a member variable of class Base. And through function show() I am able to modify the value of const variable x i.e when I print x and *ptr I get changed value in both.

class Base
{
public:
const int x;
Base(int i) : x(i) {}
virtual void show()
{
            int *ptr = const_cast<int *>(&x);        
            int *ptr = const_cast<int *>(&x);
            cout << "In Base show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};

class Derived : public Base
{
    public:
    Derived(int i) : Base(i){}
    virtual void show()
    {
            int *ptr = const_cast<int *>(&x);
            cout << "In Derived show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};
int main()
{
    Base bobj(5),*bp;
    Derived dobj(20), *dptr;
    bp = &bobj;
    bp->show();
    bp = &dobj;
    bp->show();
    return 0;
}


The output which I am getting is this 
In Base show:
Address of x    :   0x7fff82697588
Address in ptr  :   0x7fff82697588
value in x          :   5
value in ptr    :   5
After modifying 
value in x          :   15
value in ptr    :   15

In Derived show:
Address of x        :       0x7fff82697578
Address in ptr      :   0x7fff82697578
value in x          :       20
value in ptr        :       20
After modifying 
value in x          :       30
value in ptr        :       30

Can anybody help.


Solution

  • The reason is that your compiler has inlined the value of i into the code when compiling this line:

    cout << "i: " << i << "\t*ptr: " << *ptr << endl;

    Because i is a const variable, the compiler has optimised the code by replacing i in the above line with 10. If we look at the generated assembly (I'm using VS2010):

    002314F2  mov         ecx,dword ptr [ptr]  // ptr is being pushed here (110)
    002314F5  mov         edx,dword ptr [ecx]  
    002314F7  push        edx  
    002314F8  push        offset string "\t*ptr:      " (23783Ch)     
    002314FD  mov         ebx,esp  
    002314FF  push        0Ah  //  0Ah is being pushed here (A is hex for 10)
    00231501  push        offset string "i:     " (237830h) 
    

    What has happened is that you have modified the constant in memory, but the generated assembly doesn't actually use the memory address - it simply outputs '10' regardless of what's in memory.

    As said by Kerrek, this is undefined behavior, so other compilers may do something completely different to this.

    In general it is a bad idea to use const_cast with few exceptions.