behavior of const_cast in C++

1k views Asked by At

Here is my problem, the problem is in comments

const int a = 5;
const_cast<int&>(a)=7; //throw over const attribute in a,and assign to 7
std::cout<<a<<std::endl; //why still out put 5!!!!!!!!!!

Who can tell me why, and some books account these problems to recommend ? Thanks!

3

There are 3 answers

1
WhozCraig On BEST ANSWER

As-written the way you're doing this is undefined behavior. If you wanted to see the effects of const_cast<> in a defined manner:

int a = 5;                  // note: not const. regular object.
const int& cref = a;        // const-reference to same object.
cref = 7;                   // illegal. cref is a const reference.
const_cast<int&>(cref) = 7; // legal. the original object a is not const.

The only reason this is defined behavior is due to the non-const nature of the original variable, a. You cannot take an outright-const object and simply cast away the const-ness, which is what your posted code did. (at least as it has been explained to me on several occasions).

7
Jeff On

The compiler is cheating you, since this (edit: the way you used it above exactly.) is explicitly undefined behavior. When it sees the a constant defined in the same scope as the cout statement, it's not bothering to even look at memory, most likely.

You could make a more contrived example to fool your compiler, but the following modification gives me the results you want in gcc at least:

volatile const int a = 5;

To clarify, not all const_cast usage is undefined behavior, see WhozCraig's example.

0
Shafik Yaghmour On

The draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 says:

[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior

So any behavior is possible but you should not be doing this and you definitely can not rely on this behavior. Of course const_cast does have valid uses as the accepted answer in Is const_cast safe? says:

const_cast is safe only if you're casting a variable that was originally non-const.[...]

We can see one way the results you are seeing can happen from this live example that gcc 4.8.1 without any optimization is just using the value 5 instead of reading the current value:

movl    $7, (%rax)
movl    $5, %esi
movl    $_ZSt4cout, %edi

in the non const case we will see something like this:

movl    $7, -4(%rbp)
movl    -4(%rbp), %eax
movl    %eax, %esi
movl    $_ZSt4cout, %edi