虚拟化非最终方法 [英] Devirtualizing a non-final method
问题描述
假设我的类设置如下:
class A {
public:
virtual void foo() { printf("default implementation\n"); }
};
class B : public A {
public:
void foo() override { printf("B implementation\n"); }
};
class C : public B {
public:
inline void foo() final { A::foo(); }
};
int main(int argc, char **argv) {
auto c = new C();
c->foo();
}
一般来说,可以调用 c-> ; foo()
被虚拟化并内联到 printf(default implementation)
call?这是保证,例如在gcc?我的直觉是, A :: foo()
是非虚拟的,因为类是明确指定的,因此 printf
将始终内联。
In general, can the call to c->foo()
be devirtualized and inlined down to the printf("default implementation")
call? Is this guaranteed, for example in gcc? My intuition is that A::foo()
is non-virtual because the class is specified explicitly, and so the printf
will always be inlined.
推荐答案
您正在询问优化,所以一般来说,我们必须选择一个编译器, 。我们可以查看汇编输出以确定编译器是否按照您想要的方式进行优化。
You're asking about optimizations, so in general we have to pick a compiler and try it. We can look at the assembly output to determine if the compiler is optimizing the way you want.
.LC0:
.string "B implementation"
B::foo():
movl $.LC0, %edi
jmp puts
.LC2:
.string "default implementation"
A::foo():
movl $.LC2, %edi
jmp puts
C::foo():
movl $.LC2, %edi
jmp puts
main:
subq $8, %rsp
movl $8, %edi
call operator new(unsigned long)
movl $.LC2, %edi
call puts
xorl %eax, %eax
addq $8, %rsp
ret
让我们试试Clang 3.6 :
And let's try out Clang 3.6:
main: # @main
pushq %rax
movl $.Lstr, %edi
callq puts
xorl %eax, %eax
popq %rdx
retq
.Lstr:
.asciz "default implementation"
在这两种情况下,您可以清楚地看到所有的虚拟函数都已内联。
In both cases you can see that pretty clearly that all of the virtual functions have been inlined.
如果编译器确信对象的实际类型是什么,那么我怀疑这种优化总是会发生。我没有任何东西来支持这个声明。
If the compiler is confident about what the actual type of an object is, then I suspect this optimization will always happen. I don't have anything to back up this claim though.
这篇关于虚拟化非最终方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!