Question

Consider the following example:

#include <iostream>

using std::endl;
using std::cout;

class my_class {
private:
    int _expensive_count_operation() const {
        return 10;
    }
    bool cached;
    int last_count;
public:
    my_class() { cached = false; }
    int get_count() {
        if (cached) {
            cout << "Got count from cache." << endl;
            return last_count;
        }
        cout << "Computing count." << endl;
        last_count = _expensive_count_operation();
        cached = true;
        return last_count;
    }

    int get_const_count() const {
        my_class* _this = const_cast<my_class*>(this);

        if (cached) {
            cout << "Got count from cache." << endl;
            return last_count;
        }
        cout << "Computing count." << endl;
        _this->last_count = _expensive_count_operation();
        _this->cached = true;
        return last_count;
    }
};

int main() {
    my_class my_object1,my_object2;
    int count;
    count = my_object1.get_count();
    cout << "Count: " << count << endl;
    count = my_object1.get_count();
    cout << "Count: " << count << endl;

    count = my_object2.get_const_count();
    cout << "Count: " << count << endl;
    count = my_object2.get_const_count();
    cout << "Count: " << count << endl;

}

The use of const_cast in the get_const_count method allows you to keep the method const. Now the question is what are the dangers associated with this? And how do they compare to the dangers associated with loosing the ability to use const instances (or pointers to them) of this class? And, even better, is there a better approach?

I often find myself in this situation where I have written code that I then want to optimize using caching. The problem is that I then have to remove the const declarations and propagate that change through the rest of the code base.

Was it helpful?

Solution

I would prefer to mark all cache related attributes as mutable. The meaning of const should be that the observable state is not affected by those methods (which is what your cache should do anyway). Keep in mind that all const-methods should also be thread-safe.

For further information I recommend the blog of Herb Sutter - he wrote some stuff about const-correctness since c++11. Here is also a direct Link to a related video from Herb.

OTHER TIPS

It is ONLY valid to use const_cast to remove const if the original object was NOT const. If that is always the case, it should be no problem to do this.

Although I would prefer to set last_count and cached to mutable... Because you don't really want to accidentally modify any of the other parts of the object - but you DO want to modify those in the const member function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top