由派生类调用时的虚函数性能
Virtual function performance when called by derived classes?
在编译时从已知为派生类的类调用虚拟方法时,是否会降低性能? 下面我显式调用force_speak
派生类。
法典:
#include <iostream>
#include <array>
#include <memory>
class Base
{
public:
virtual void speak()
{
std::cout << "base" << std::endl;
}
};
class Derived1 : public Base
{
public:
void speak()
{
std::cout << "derived 1" << std::endl;
}
};
template<class B>
void force_speak(std::array<std::unique_ptr<B>, 3>& arr)
{
for (auto& b: arr)
{
b->speak();
}
}
int main()
{
std::array<std::unique_ptr<Derived1>, 3> arr =
{
std::unique_ptr<Derived1>(new Derived1),
std::unique_ptr<Derived1>(new Derived1),
std::unique_ptr<Derived1>(new Derived1)
};
force_speak(arr);
return 0;
}
在编译时从已知为派生类的类调用虚拟方法时,是否会降低性能?请参阅下面的代码。
这要看情况。大多数编译器会像这样"去虚拟化"代码:
Derived1 d;
d.speak();
对象的动态类型在调用站点是已知的,因此编译器可以避免通过 vtable 进行调用,而可以直接调用Derived1::speak()
。
在您的示例中,编译器需要更智能,因为force_speak
中只有Derived1*
指针(存储在unique_ptr
对象中(,在该上下文中,不清楚指向对象的动态类型是Derived1
还是更派生的类型。 编译器需要内联调用以force_speak
main
(动态类型已知(,或者使用有关类型的一些其他知识来允许进行虚拟化解冻。(作为附加知识的一个示例,整个程序优化可以确定程序中的任何地方都没有声明其他派生类型,因此Derived1*
必须指向Derived1
。
使用 C++11 final
关键字可以帮助编译器对某些情况进行去虚拟化,例如,如果Derived1
被标记为final
则编译器知道Derived1*
只能指向Derived1
,而不能指向从中派生的可能覆盖speak()
的其他类型
-
它依赖于编译器。编译器必须静态地知道
Derived1:speak()
是唯一的选择。这包括知道没有一些Derived2::speak()
定义,其中class Derived2: public Derived1
.但是编译器可能根本不实现这样的优化。 -
函数模板参数可由编译器自动推导。这是C++标准的一部分。编译器知道调用站点上的参数类型,因此用户不必提供它。请注意,用户可以提供类型,而 thay 可以提供例如类型兼容但不同于实际参数的类型。
在这种特定情况下,答案是也许。
如果编译器决定内联force_speak()
理论上可以推断出数组中的所有指针都是Derived1
实例,因此静态调用该方法。 (标准不需要此优化,因此是静态调用方法还是虚拟调用该方法取决于您的特定编译器以及编译期间可能使用的选项。
如果编译器不内联调用,那么它必须发出指令以虚拟调用该方法,因为您可以进一步派生类Derived1
并再次覆盖该方法,将该类的实例存储在std::unique_ptr<Derived1>
中,并将这些实例的数组传递到函数中。
- 如何比较两个函数的速度和性能
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 函数局部静态变量:从性能角度来看的优点/缺点
- C++ 将函数指针与最佳性能相结合
- 为什么使用默认构造函数"{}"而不是"= default"存在性能变化?
- 通过默认复制构造函数比较 C++ 字符串是否会影响性能,原因为何?
- 隐式转换函数的返回对象时是否会影响性能?
- 虚拟函数调用的性能作为 for 循环中的上限
- 如何提高对 std::函数侦听器的分发性能?
- 性能函数调用与乘以 1
- C++构造函数性能
- 课堂初始化(分配样式)与构造函数性能
- 类方法VS类静态函数VS简单函数-性能方面
- 对同一对象进行x调用的c++虚拟函数性能
- 由派生类调用时的虚函数性能
- c++ 11委托的函数是否比c++ 03调用init函数的函数性能差?
- 捕获Lambda函数性能的影响
- Visual c++中的函数性能计数器
- 从另一个操作符重载函数调用操作符重载函数:性能
- 内联函数性能