-2

I have this piece of code:

#include <iostream>    
using namespace std;

class X {

    public:
        const int x;
        X(int i) : x(i) {  }            
        int getX() const { return x; }           
};

int main()
{
      const X d(45);

      const_cast<X *>(&d)->x = 47;
      cout << d.getX() << endl;

      const int j = 3; // j is declared const
      int* pj = const_cast<int*>(&j);
      *pj = 4; 
      cout << *pj << endl; //should not work, like above

      return 0;
}

As I found here, Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior. They even proceed to provide examples below, the second one I gave, stating that it should give undefined behavior.

However, on compiling the code and running (here), the second one gives no error, and prints out 4 consistently. Whereas the first one throws error:

assignment of read-only member 'X::x'                            
       const_cast<X *>(&d)->x = 47;

Of course, removing the const from declaration of x in X makes it work fine. However, it is also of the same type of mischief as the first one, changing a const thing through pointer after casting it const_ptr<>. But the first one works while the second one doesn't. Why so?

SexyBeast
  • 7,913
  • 28
  • 108
  • 196
  • 5
    "Undefined behavior" != "Must crash". Moreover, very often it means "works with no visible signs of a problem". – Sergey Kalinichenko Jan 11 '15 at 13:18
  • So, the `4` I am getting is undefined behavior? I am not supposed to get it? – SexyBeast Jan 11 '15 at 13:19
  • "Undefined" means that The Standard provides no guidance whatsoever regarding what the program should do. It does not mean that you'll be able to observe anything odd or receive an error message. – molbdnilo Jan 11 '15 at 13:19
  • 1
    @Cupidvogel: Yes, getting `4` is one possible instance of undefined behaviour. Asking what undefined behaviour is "supposed" to do is meaningless. – Mike Seymour Jan 11 '15 at 13:22
  • Yes yes, that's what I was saying, so 4 coming as answer consistently is part of being undefined, and is not guaranteed, correct? – SexyBeast Jan 11 '15 at 14:20
  • [How to explain undefined behavior to know-it-all newbies?](https://stackoverflow.com/questions/2235457/how-to-explain-undefined-behavior-to-know-it-all-newbies) <-- I'm surprised this question exists. –  Jan 11 '15 at 14:34
  • My question is, if both are undefined behavior, then why is compiler throwing an error in one case and not in the other? – SexyBeast Jan 11 '15 at 15:06

2 Answers2

1

Both demands undefined behavior which unfortunately could mean working sometimes.

   int* pj = const_cast<int*>(&j);
   *pj = 4; 

Also, Not all compilers are smart enough to figure out this kind of indirect manipulation.

ravi
  • 10,994
  • 1
  • 18
  • 36
0

Const-casting anything other than an actual const ptr* is probably a terrible idea, even if it does actually work most of the time.

That being said, the reason why your code doesn't compile properly is pretty straightforward: you remove the constness of the X object, but you fail to also remove the constness of the x member you're trying to modify.

Try this:

*const_cast<int*>(&(const_cast<X*>(&d)->x)) = 47;
chili
  • 665
  • 8
  • 20