Insight Into const_cast on const data-members

This is a discussion on Insight Into const_cast on const data-members within the C++ Programming forums, part of the General Programming Boards category; Hi,
We had a discussion on this board regarding the usefulness of const_cast.
"if a variable is const at its ...

Insight Into const_cast on const data-members

We had a discussion on this board regarding the usefulness of const_cast.

"if a variable is const at its point of definition, the result of
casting it away are undefined".

Polymorphic OOP suggested that this rule might not be applicable on non-static const datamembers.

Below mentioned is the extract of the email-interaction between "Bjarne Stroustrup" and me

---------------- My Question --------------------
Sir,
You have suggested that

const int i = 10;

int *p = const_cast<int *>(&i);

*p = 20; // Result is undefined

"if a variable is const at its point of definition, the result of
casting it away are undefined".

My question is "are datamembers an exception to to this suggestion?"
---------------------------My Question Ends Here ---------------

-------------- Bjarne Stroustrup's Answer ----------------------

No, and it's not a "suggestion" its a rule of the language. An
implementation is allowed to place a const in unwritable memory, such as a code segment, so that the *p=20 causes a run-time hardware exception. This is sometimes done in embedded systems where RAM is scarce and ROM cheaper.

This goes back to the same reason that const function parameters can be editted (which was the example that you pointed out). When data is on the stack, it's guaranteed to have a writable memory location. The same goes with data on the heap, or any type of const that can be initialized with a different value at runtime. A nonstatic const datamember which can be initialized differently for each object at runtime must be stored with that structure in each object as defined by the standard. That means that if the object is in writable memory, then the nonstatic const datamember is as well (whether it be on the stack, heap, in data, etc.). The standard states that const data CAN be placed in unwritable memory -- however, if it DID in this case, it would be contradictory. Stroustrup probably thought you meant a const int which is initialized in the class definition (which is in all actuality just a static const).

Yeah, according to the standard, if it were possible, the data could potentially not be editted, but it is literally impossible in this case to make the const in unwritable memory without going against other things in the standard. It can't get a runtime error because it is in the same place that a nonconst piece of data could be stored. If there was a pointer to the memory not denoted by const (IE if the const was casted away), neither the program nor the "pointer" nor anything else would know if it pointed to const data. It would be completely oblivious, even at runtime.

We can't conclude

Originally posted by Polymorphic OOP Yeah, according to the standard, if it were possible, the data could potentially not be editted, but it is literally impossible in this case to make the const in unwritable memory without going against other things in the standard. It can't get a runtime error because it is in the same place that a nonconst piece of data could be stored. If there was a pointer to the memory not denoted by const (IE if the const was casted away), neither the program nor the "pointer" nor anything else would know if it pointed to const data. It would be completely oblivious, even at runtime.

Hi Ploymorphic OOP,

Your observations w.r.t memory being allocated in the writable / non-writable memory understood and well taken.......

Having said that we can't take a definite stance on this topic with your observations..... everything becomes very relative.

Its preferable if we take the standards as the "Final Say" and just code things that comply with the standard and never do anything (even if it works) that are not supported / suggested by the standard

let me get this straight,
When I create a constant in main, I am directly initializing it to a constant but in a class the initialization is done per object which means there are multiple copies of that constant variable, hence it can be modified using the const_cast.

am i getting this right ?
one more thing do all compliers behave like this or is it specific to MSVC++

Originally posted by newt let me get this straight,
When I create a constant in main, I am directly initializing it to a constant but in a class the initialization is done per object which means there are multiple copies of that constant variable, hence it can be modified using the const_cast.

Only if you initialize it to a variable on a per object basis.

If you initialize it in main to a variable the same thing would be true.

The actual results are not defined by the standard. I was just making the point that in order to comply with other things in the standard, those constants have to have valid writable memory locations (unlike most other types of constants). You still should NOT do it as the results are still "undefined."

hmmm......
so when ever I create a variable and assign it to a constant the
constant is modified ( using const_Cast )
but a literal is hard coded and is not erased.
so the compiler must be substituting the 10 directly ( from the ROM area) where as in case of the variable it just passes the address of the variable, which IS modifiable...

Just one more thing then:
The address stored in the pointer and the address of the constant is the same, so how can two values reside in the same location
const int i = 10;
int *ptr = NULL;
ptr = const_cast<int*>(&i);
cout<<*ptr<<endl;
*ptr = *ptr + 100;
cout<<*ptr<<endl;
cout<<i<<endl;
cout<<ptr<<"\t"<<&i<<endl;

when the standard says that the above operation result is undefined then you could say it is also compiler dependent ...
some compilers might throw up an error others might just give different outputs ( like in my case ).

Just one more thing then:
The address stored in the pointer and the address of the
constant is the same, so how can two values reside in the same
location

Well whenever the compiler creates a constant in the non-writable area,
we have a direct substituion for that constant-reference to value...
hence does not reach out to the RAM

Code:

const int i = 10; // this could be completely optimized

Having said that if you have created the constant in such a way
that it can't just stop there.. but has to allocate memory, then it
does allocate the same too. The pointers that point to this const,
get that address

Code:

const int i = 10;
int *p = const_cast<int *>(&i);
// since u r taking the address of i,
//it has no choice but to allocate memory
*p = 30; // will change the value at the memory allocated for i,
cout << i; // gives u 10
// but still everywhere u use i, it would be an assembly level
//direct substitution and hence it does not go to the location to
//fecth the value