Search code examples
c++thisconst-cast

const_cast(this) performance hit


As far as I know , making constant functions in a class is useful for read/write compiler optimizations.

A constant function within a class means that the class members will remain constant during the execution of the function. However, you can bypass this by const casting the implicit parameter (ofc this is a very bad practice).

My questions is as follows :

What pitfalls can the following code cause (especially in terms of performance unrelated to thread synchronization) ?

 int myClass::getSomething() const
 {
     myClass* writableThis = const_cast<myClass*>(this);
     writableThis->m_nMemberInt++;
     ...
     return m_nSomeOtherUnchangedMember;
 }

Another related question :

Is the behavior compiler/platform/os specific ?

I would also very much appreciate if someone could explain the magic under the hood when such a code is compiled/executed (I'm speculating that the CPU is making out-of-order optimizations based on the fact that the function is const , and not respecting this during actual execution should have some side effects).

EDIT :

Thank you for clarifying this for me. After further research all the received answers are correct but I can accept only one :).

Regarding the const qualifier being used solely for syntax corectness , I believe this answer is both right and wrong, the correct way to state this (imho) would be that it is used mostly for syntax corectness (in a very limited number of scenarios it can produce different / better code ). References : SO Related question , related article


Solution

  • The const_cast<T>(this) trick is potentially unsafe, because the user of your member function may run into undefined behavior without doing anything wrong on their side.

    The problem is that casting away const-ness is allowed only when you start with a non-const object. If your object is constant, the function that casts away its const-ness and uses the resultant pointer to change object's state triggers undefined behavior:

    struct Test {
        int n;
        Test() : n(0) {}
        void potentiallyUndefinedBehavior() const {
            Test *wrong = const_cast<Test*>(this);
            wrong->n++;
        }
    };
    
    int main() {
        Test t1;
        // This call is OK, because t1 is non-const
        t1.potentiallyUndefinedBehavior();
        const Test t2;
        // This triggers undefined behavior, because t2 is const
        t2.potentiallyUndefinedBehavior();
        return 0;
    }
    

    The trick with const_cast<T>(this) has been invented for caching values inside member functions with const qualifier. However, it is no longer useful, because C++ added a special keyword for this sort of things: by marking a member mutable you make that member writable inside const-qualified methods:

    struct Test {
        mutable int n;
        Test() : n(0) {}
        void wellDefinedBehavior() const {
            n++;
        }
    };
    

    Now the const member function will not trigger undefined behavior regardless of the context.