From my understanding , mutable
cancels the constness
of a variable
Class A {
void foo() const {
m_a = 5;
}
mutable int m_a;
};
The difference is that const_cast
can't cheat, but mutable
is an exception to the rules.
On the first snippet m_a
is mutable
, and thus an exception to the rule that you can't modify data members on const
member functions.
On the second snippet, const_cast
tries to cheat, but really can't: while the type has changed, actual modification is not allowed: the string is truly const
. Attempting to modify it would cause the program to exhibit undefined behaviour.
const_cast
cannot cancel constness of an object. const_cast
can only remove constness from an access path to an object. Access path is a pointer or a reference to an object. Removing the constness from the access path has absolutely no effect on the object itself. Even if you use const_cast
to remove the constness of the access path, that still does not necessarily give you the permission to modify the object. Whether you can do it or not still depends on the object itself. If it is const, you are not allowed to modify it and any attempts to do so will result in undefined behavior.
For example, this illustrates the intended use of const_cast
int i = 5; // non-constant object
const int *p = &i; // `p` is a const access path to `i`
// Since we know that `i` is not a const, we can remove constness...
int *q = const_cast<int *>(p);
// ... and legally modify `i`
*q = 10;
// Now `i` is 10
The only reason the above is legal and valid is the fact that i
is actually a non-constant object, and we know about it.
If the original object was really constant, then the above code would produce undefined behavior:
const int j = 5; // constant object
const int *p = &j; // `p` is a const access path to `j`
int *q = const_cast<int *>(p); // `q` is a non-const access path to `j`
*q = 10; // UNDEFINED BEHAVIOR !!!
C++ language does not allow you to modify constant objects and const_cast
is completely powerless here, regardless of how you use it.
mutable
is a completely different thing. mutable
creates a data filed that can be legally modified even if the containing object is declared const
. In that sense mutable
does allow you to modify [some designated parts of] constant objects. const_cast
, on the other hand, can't do anything like that.
Simply put, declaring a member variable as mutable
makes it write-accessible from any constant method of that class without any other special syntax. const_cast
on the other hand has to be performed whenever you want write access to an otherwise constant variable, and that variable doesn't even have to be a class member.
Unless you want to explicitly allow write access to a member variable, using const_cast
in every case of violation of const correctness is preferred, if only to clearly state your intentions.
On a side note, const_cast can also be used to add or remove the volatile
modifier.
The difference is semantic - i. e. same generated code, same run-time results (const
ness is a purely compile-time construct anyway), but the two constructs convey a slightly different meaning.
The idea is that you use mutable
for variables that are in the class, but don't constitute the state of the object. The classic example is the current position in a blob object. Navigating in the blob does not count as "modifying" the blob in a way that matters. By using mutable
, you're saying "this variable may change, but the object is still the same". You're stating that for this particular class, const
-ness does not mean "all variables are frozen".
const_cast
, on the other way, means that you're violating existing const correctness and hope to get away with it. Probably because you're working with a 3rd party API that does not respect const
(e. g. an old school C-based one).