...
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 cachedValue
results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> class S { int cachedCalccachedValue; int expensivecompute_computevalue() const; // expensive public: S() : cachedCalccachedValue(0) {} // ... int calculateget_value() const { if (!cachedCalccachedValue) { const_cast<S *>(this)->cachedCalc>cachedValue = expensivecompute_computevalue(); } return cachedCalccachedValue; } }; void f() { const S s; std::cout << s.calculateget_value() << std::endl; } |
Compliant Solution
This compliant solution uses the mutable
keyword when declaring cachedCalc
cachedValue
, which allows it to be mutated within a const
context without triggering undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream> class S { mutable int cachedCalccachedValue; int expensivecompute_computevalue() const; // expensive public: S() : cachedCalccachedValue(0) {} // ... int calculateget_value() const { if (!cachedCalccachedValue) { cachedCalccachedValue = expensivecompute_computevalue(); } return cachedCalccachedValue; } }; void f() { const S s; std::cout << s.calculateget_value() << std::endl; } |
Noncompliant Code Example
...