Home > Net >  Why doesn't the optimizer optimize this code?
Why doesn't the optimizer optimize this code?

Time:03-16

Compiling and running this code with the maximum optimization settings seems to give the same result.

#include <stdio.h>

class A
{
public:
    A() { }
    const int* begin() const { return a; };
    const int* end() const { printf("end\n"); return a   3; };
    bool isTrue() const { return true; }
    int a[4];
};

const A a{};

class B
{
public:
  const A& operator[](size_t) const { printf("B called\n"); return a; }
};


int main()
{
    const B b{};
    if (!b[0].isTrue()) return -1;
    for (const auto& x : b[0]) printf("%d\n", x);
}

I call b[0] twice on a constant object of type B which operator[] returns a constant object of type A.

Why does "B called" get printed twice? Why can't the code save b[0] on the side and run on it different functionality? (Since the functions are const functions, they will return the same result...)

CodePudding user response:

Why does "B called" get printed twice?

For starters, because you reference b[0] twice in main. And because the printf statement inside the operator function dictates that there's a side effect for accessing b[0]. So the compiler can't assume that your printf is just for debugging - it has to invoke it once for each call.

Using godbolt, if we remove the printf statements and evaluate, we can see the code is heavily optimized to print 0 three times without any calls whatsoever.

Optimized: https://godbolt.org/z/E8czPdr5W

CodePudding user response:

operator[] is a normal function like any other and since C has no notion of pure functions the compiler has to assume that every function has side effects. One such side effect is your printf call. If you optimize away one of the calls to operator[], your program behavior can change (here it would only print once instead of twice). Imagine that instead of printf you would do a call to a database or something other important. That would be really bad if it was just optimized away.

Also note that const member functions are not the same as pure functions. const means it cannot modify the instance that you call the member function on, but you can still change global variables for example. And you aren't even guaranteed that the const member function won't change the state of the instance, because you can cast away const under certain conditions.

  • Related