-3

Let's see the example first.

#include <iostream>
int main()
{
    const int constant = 1;
    const int* const_p = &constant;
    int* modifier = const_cast<int*>(const_p);
    *modifier = 100;
    std::cout << "constant: " << constant << ", *const_p=" << *const_p;
    //Output: constant: 1, *const_p=100
    return 0;
}

I don't know how it achieved in the memory architecture. It seems that the compiler have occupied extra memory space in the stack so that we can keep track of the "original" constant whose value is 1, and a new memory location in the stack whose value is 100. Is it? So will const_cast indeed consume extra memory as a beginner might not first expect?

Eric
  • 185
  • 7
  • 1
    Please show a [mcve], a complete function, not only a code snippet without context. – Jabberwocky Jul 04 '22 at 12:14
  • 4
    No, but this leads to undefined behavior (basically means anything can happen situation). – Marek R Jul 04 '22 at 12:14
  • Attempting to modify constant data leads to *undefined behavior*. – Some programmer dude Jul 04 '22 at 12:15
  • Related to the undefined behavior. It might be that the compiler decided to put your const int in read only memory, as it was const upon declaration. So even though you're casting away const, there's no possible way you could modify that value. – Tohnmeister Jul 04 '22 at 12:21
  • A beginner might think const_cast is a nice thing, since adding that to code will make it compile. In practice const_cast is one of those things you should use with utmost care (if at all) if you really can't find another solution like using a local writable copy (and again in some specific cases the use of the mutable keyword). – Pepijn Kramer Jul 04 '22 at 13:04
  • 1
    `const_cast` is used to cast away const-ness in situations where the thing is *actually* not `const`. "Trust me compiler, it's really not const." In this code, the thing is *actually* `const`. C++ is not a nanny language, it presumes your code is correct — lie to the compiler, and the compiler will blithely generate code that goes straight into the giggleweeds. This code is ill-formed. – Eljay Jul 04 '22 at 13:22

1 Answers1

5

This

*modifier = 100;

is undefined. You cannot change the value of a const int.

You can cast away constness but you cannot possibly modify something that is constant. A correct usage of the const cast would be for example:

int not_constant = 1;                            // not const !!
const int* const_p = &not_constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 100;                             // ok because not_constant is not const

No "extra memory" is being used here.


What happens in your code is probably that the compiler sees

std::cout << "constant: " << constant << ", *const_p=" << *const_p;

And the compiler "knows" that const int constant cannot possibly change its value after initialization, hence it can replace that line with

std::cout << "constant: " << 1 << ", *const_p=" << *const_p;
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 2
    I think the OP's confusion is from the fact that it looks there are two values in the same memory address, while it's just compiler optimization (since it knows value of `constant` cannot change, it probably replaced `std::cout << constant` with `std::cout << 1` – Yksisarvinen Jul 04 '22 at 12:21
  • 1
    @Yksisarvinen ok I just handled this by stating it is undefined, perhaps a little more information would help... – 463035818_is_not_an_ai Jul 04 '22 at 12:22
  • 3
    It's a good answer, I just thought it may be useful to clarify that compiler doesn't need "a new memory location in the stack" for anything as OP suggested, it's more likely doing an optimization (which makes the results weird due to UB). – Yksisarvinen Jul 04 '22 at 12:26
  • Yes, what I thought was exactly what @Yksisarvinen said. And this answer is quite comprehensive! Thank you all. – Eric Jul 04 '22 at 13:52
  • @Eric eventually I found what I was looking for https://stackoverflow.com/a/856839/4117728. This is a nice example of an completely "ok" `const_cast`. In the non-const getter you can call the const one and because you know for sure that the actual object is not `const` you can cast away the `const` from the returned reference – 463035818_is_not_an_ai Jul 04 '22 at 13:58