Weird Behaviour with Const_Cast

Strange behavior of const_cast

Modifying a constant object gives undefined behaviour, so your program could (in principle) do anything.

One reason for leaving this behaviour undefined is to allow the optimisation of replacing a constant variable with its value (since you've stated that the value can never change). That's what is happening here: a is replaced with the value 7 at compile time, and so will keep that value whatever you try to do to it at run time.

Weird Behaviour with const_cast

So, aside from the "it's undefined behaviour" (which it is), the compiler is perfectly fine to use the fact that M is a constant, thus won't change, in the evaluation of cout ... << M << ..., so can use an instruction that has the immediate value 10, instead of the actual value stored in the memory of M. (Of course, the standard will not say how this works, more than "it's undefined", and compilers are able to choose different solutions in different circumstances, etc, etc, so it's entirely possible that you'll get different results if you modify the code, use a different compiler, different version of compiler or the wind is blowing in a different direction).

Part of the tricky bit with "undefined behaviour" is that it includes things that are "perfectly what you may expect" as well as "nearly what you'd expect". The compiler could also decide to start tetris if it discovers this is what you are doing.

And yes, this is very much one of the reasons why you SHOULD NOT use const_cast. At the very least NOT on things that were originally const - it's OK if you have something along these lines:

int x;

void func(const int* p)
{
...
int *q = const_cast<int *>(p);

*q = 7;
}

...

func(&x);

In this case, x is not actually const, it just becomes const when we pass it to func. Of course, the compiler may still assume that x is not changed in func, and thus you could have problems....

behaviour of const_cast

it helps to cast away constness of an expression of type Type

No, Type is the type of the result, not the type of the operand.

What i think is const of this pointer should be casted away

this has type const ConstTest*. const_cast<ConstTest*>(this) has type ConstTest*. That's what "casting away const" from a pointer-to-const means.

I feel code should have been ConstTest *c =
const_cast<ConstTest>(*this)

The result of const_cast<T> has type T, that's how it's defined. Maybe you would have defined it differently, but tough luck, you don't get a ConstTest* by writing const_cast<ConstTest>, you get it by writing const_cast<ConstTest*>. Your preferred syntax is not available.

You can either do ConstTest &c = const_cast<ConstTest&>(*this) or ConstTest *c = const_cast<ConstTest*>(this), so pick your favorite.

The result of a const_cast expression is an rvalue unless Type is a
reference type. In this case, the result is an lvalue.

why so and why it is not true in case of pointers?

It is true of pointers. ConstTest* is not a reference type, and the result of const_cast<ConstTest*>(this) is an rvalue. You then assign that value to the variable c.

Undefined behavior when adding a const with const_cast?

You are casting the function pointer, not the pointer returned by the function. Call the function first with (), then cast the result.

EDIT: I can't reproduce the problem. Here's the code I used:

#include <cstdlib>
#include <iostream>

using namespace std;
int main() {
const char * org_str = NULL;
org_str = const_cast<const char*>(getenv("PATH"));
cout << "Got: " << org_str << endl;
}

Here's what I got:

$ g++ foo.cc -o foo.app
$ ./foo.app
Got: /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/X11R6/bin
$

BTW, the assignment to NULL is unnecessary; recommended practice is to use one of:

const char *org_str = const_cast<const char*>(getenv("PATH"));

const char *org_str(const_cast<const char*>(getenv("PATH")));

const char *org_str(getenv("PATH"));

change the value of const_cast ptr/ref doesn't change the original object value?

If you spell out the type of ptr2i you get:

const int * ptr2i = &i;  // since i is const

Now you can const_cast this const int * to an int *:

auto pp = const_cast<int*>(ptr2i);  // ok

But the pointed at variable i has type const int, so if you then try to modify this pointed at value:

*pp = 456;  // oops, UB since you are attempting to modify i

you invoke undefined behavior. This can result in a program that does anything, including showing different values at the same address.

The same restrictions apply when you cast a const int & to an int & and then try to modify it.

The problems of const data in c++

While I use *ptr, I can change the const data *a. Why?

Because your program is causing undefined behavior. You lied to the compiler that b is non-const by casting const-ness away from the pointer produced by &b, but writing to that pointer on the *c = 200 line is undefined behavior.

Both the address of b and *c are the same, but the data are different. Why?

It happens for the same reason: the behavior is undefined.

As for the real-life scenario when this would happen, I would speculate that the compiler has optimized out the read of b, because you promised it that b is const. However, the compiler found a clever way of getting back at you by replacing a read of the actual b with the output of a constant that has been assigned to b originally.



Related Topics



Leave a reply



Submit