问题
int main()
{
const int maxint=100;//The program will crash if this line is put outside the main
int &msg=const_cast<int&>(maxint);
msg=200;
cout<<"max:"<<msg<<endl;
return 0;
}
The function will run ok if the 'const int maxint=100;' definition is put inside the main function but crash and popup a error message said "Access Violation" if put outside.
Someone says it's some kind of 'undefined behavior', and i want to know the exact answer and how i can use the const cast safely?
回答1:
They are correct, it is undefined behaviour. You're not allowed to modify the value of a const
variable, which is the danger of casting away the const
ness of something: you better know it's not really const
.
The compiler, seeing that maxint
is const
and should never be modified, doesn't even have to give it an address. It can just replace all the uses of maxint
with 100 if it sees fit. Also it might just put the constant in to a portion of memory that is read-only, as Matteo Italia points out, which is probably what's happening for you. That's why modifying it produces undefined behaviour.
The only way you can safely cast away the const
ness of a variable is if the variable is not actually const
, but the const
qualifier was added to a non-const
variable, like this:
int f(const int& x) {
int& nonconst = const_cast<int&>(x);
++nonconst;
}
int blah = 523;
f(blah); // this is safe
const int constblah = 123;
f(constblah); // this is undefined behaviour
Think about this example, which compiles perfectly:
int f(const int& x) {
int& nonconst = const_cast<int&>(x);
++nonconst;
}
int main() {
f(4); // incrementing a number literal???
}
You can see how using const_cast
is pretty dangerous because there's no way to actually tell whether a variable is originally const
or not. You should avoid using const_cast
when possible (with functions, by just not accepting const
parameters).
回答2:
Modifying an object that is const
(with the exception of mutable members) results in undefined behavior (from the C++03 standard):
7.1.5.1/4 "The cv-qualifiers"
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
The above undefined behavior is specifically called out in the standard's section on const_cast
:
5.2.11/7 "Const cast"
[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier68) may produce undefined behavior (7.1.5.1). ]
So, if you have a const
pointer or reference to an object that isn't actually const
, you're allowed to write to that object (by casting away the constness), but not if the object really is const
.
The compiler is permitted to place const
objects in read-only storage, for example. It doesn't have to though, and apparently doesn't for your test code that doesn't crash.
回答3:
You are only allowed to cast away constness of an object which is known not to be const
. For example, an interface may pass objects through using a const
pointer or a const
reference but you passed in an object which isn't const
and want/need to modify it. In this case it may be right thing to cast away constness.
On the other hand, casting away constness of an object which was const
all the way can land you in deep trouble: when accessing this object, in particular when writing to it, the system may cause all kinds of strange things: the behavior is not defined (by the C++ standard) and on a particular system it may cause e.g. an access violation (because the address of the object is arranged to be in a read-only area).
Note that despite another response I saw const
objects need to get an address assigned if the address is ever taken and used in some way. In your code the const_cast<int&>(maxint)
expression essentially obtains the address of your constant int which is apparently stored in a memory area which is marked to be read-only. The interesting aspect of your code snippet is that it is like to apparently work, especially when turning on optimization: the code is simple enough that the compiler can tell that the changed location isn't really used and doesn't actually attempt to change the memory location! In this case, no access violation is reported. This is what apparently is the case when the constant is declared inside the function (although the constant may also be located on the stack which typically can't be marked as read-only). Another potential outcome of your code is (independent of whether the constant is declared inside the function or not) is that is actually changed and sometimes read as 100 and in other contexts (which in some way or another involve the address) as 200.
来源:https://stackoverflow.com/questions/8663290/const-cast-to-a-global-var-and-program-crashed-c