去虚拟化非最终方法
Devirtualizing a non-final method
假设我有一个像下面这样的类设置:
class A {
public:
virtual void foo() { printf("default implementationn"); }
};
class B : public A {
public:
void foo() override { printf("B implementationn"); }
};
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")
调用吗?例如在gcc中,这是有保证的吗?我的直觉是A::foo()
是非虚拟的,因为类是显式指定的,因此printf
将始终是内联的。
你问的是优化,所以通常我们必须选择一个编译器并尝试它。我们可以查看程序集的输出,以确定编译器是否按照您想要的方式进行了优化。
让我们试试GCC 5.2:
.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:
main: # @main
pushq %rax
movl $.Lstr, %edi
callq puts
xorl %eax, %eax
popq %rdx
retq
.Lstr:
.asciz "default implementation"
在这两种情况下,你都可以很清楚地看到所有的虚函数都被内联了。
"这是保证的吗,例如在gcc中?"
如果编译器对对象的实际类型有信心,那么我怀疑这种优化总是会发生。但是我没有任何证据来支持这个说法。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 去虚拟化非最终方法