I wrote this short program to see how devirtualization would work. The compiler should be able to deduce the correct type:
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public:
void foo() { cout << "Base::foo" << endl; }
virtual void bar() { cout << "Base::bar" << endl; }
virtual ~Base() = default;
};
class Child : public Base
{
public:
void foo() { cout << "Child::foo" << endl; }
void bar() { cout << "Child::bar" << endl; }
};
int main()
{
Base* obj = new Child;
obj->foo();
obj->bar();
delete obj;
}
Compiled with -O2 -std=c++11 using gcc 5.3 and clang 3.7 via https://gcc.godbolt.org/.
What turned out is that neither compiler was able to optimize everything - gcc inlines foo() and makes virtual call to bar() while clang makes call to foo() and devirtualizes and inlines call to bar().
Meanwhile, if instead I call obj->bar(); and then obj->foo();, the compilers have no problem in optimizing - clang inlines both calls and gcc makes normal call to bar() instead of virtual one and inlines foo().
Can anyone explain this behavior?
It's probably because the compiler thinks that inlining does not help because the
coutis too expensive compared to the overhead of the function call. If you replace it with something simpler, e.g. an assigment to a member, it will get inlined. See below for the output ofAssembly: