The C++ Standard, [dcl.type.cv], paragraph 4, states 4 [ISO/IEC 14882-2014], states:
Except that any class member declared
mutable
can be modified, any attempt to modify aconst
object during its lifetime results in undefined behavior.
...
In this noncompliant code example, the function g()
is passed a const
int &
, which is then cast to an int &
and modified. Because the value referenced to was previously declared as const
, the assignment operation results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
void g(const int &ci) { int &ir = const_cast<int &>(ci); ir = 42; } void f() { const int i = 4; g(i); } |
...
In this noncompliant code example, a const
-qualified method is called, which attempts to cache results by casting away the const
-qualifier of this
. Because s
was declared const
, the mutation of CachedCalc
results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> class S { int CachedCalc; int expensiveCompute() const; public: S() : CachedCalc(0) {} // ... int Calculate() const { if (!CachedCalc) { const_cast<S *>(this)->CachedCalc = expensiveCompute(); } return CachedCalc; } }; void f() { const S s; std::cout << s.Calculate() << std::endl; } |
...
This compliant solution uses the mutable
keyword when declaring CachedCalc
, which allows it to be mutated within a const
context without triggering undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> class S { mutable int CachedCalc; int expensiveCompute() const; public: S() : CachedCalc(0) {} // ... int Calculate() const { if (!CachedCalc) { CachedCalc = expensiveCompute(); } return CachedCalc; } }; void f() { const S s; std::cout << s.Calculate() << std::endl; } |
...
In this noncompliant code example, the volatile value s
has the volatile
qualifier cast away, and an attempt is made to read the value within g()
, resulting in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> struct S { int i; S(int i) : i(i) {} }; void g(S &s) { std::cout << s.i << std::endl; } void f() { volatile S s(12); g(const_cast<S &>(s)); } |
...
[ISO/IEC 14882-2014] | 7.1.6.1, "The cv-qualifiers" |
[Sutter 04] | Item 94, "Avoid casting away const " |
...