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
How Does _Builtin_Clear_Cache Work
Converting Data from Glreadpixels() to Opencv::Mat
How to Initialize 3D Array in C++
Is Volatile Bool for Thread Control Considered Wrong
When Is a Function Try Block Useful
Overloaded Lambdas in C++ and Differences Between Clang and Gcc
Does the C++ Standard Specify Anything on the Representation of Floating Point Numbers
C++ Error: '_Mm_Sin_Ps' Was Not Declared in This Scope
Choosing Embedded Scripting Language for C++
How to Alpha Blend Rgba Unsigned Byte Color Fast
Casting via Void* Instead of Using Reinterpret_Cast
How to Store a 64 Bit Integer in Two 32 Bit Integers and Convert Back Again
Passing Functor as Function Pointer
Why Do Un-Named C++ Objects Destruct Before the Scope Block Ends