gpt4 book ai didi

c++ - 接口(interface)开销

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:48:58 29 4
gpt4 key购买 nike

我有一个看起来像 Boost.Array 的简单类。有两个模板参数 T 和 N。Boost.Array 的一个缺点是,每个使用这种数组的方法都必须是带有参数 N 的模板(T 可以)。结果是整个程序往往是一个模板。一个想法是创建一个仅依赖于 T(类似于 ArrayInterface)的接口(interface)(只有纯虚函数的抽象类)。现在每个其他类都只访问接口(interface),因此只需要模板参数 T(与 N 相比,它或多或少总是已知的)。如果使用接口(interface),这里的缺点是虚拟调用的开销(更多的是错过了内联调用的机会)。直到这里只有事实。

template<typename T>
class ArrayInterface {
public:
virtual ~ArrayInterface() {};
virtual T Get(int i) = 0;
};

template<typename T, int N>
class Array : ArrayInterface<T> {
public:
T Get(int i) { ... }
};

template<typename T, int N>
class ArrayWithoutInterface {
public:
T Get() { ... }
};

但我真正的问题在于其他地方。当我使用接口(interface)扩展 Boost.Array 时,Boost.Array 的直接实例化变慢(在一种情况下,因素 4,这很重要)。如果我删除接口(interface),Boost.Array 和以前一样快。我知道,如果通过 ArrayInterface 调用方法会产生开销,那没关系。但是我不明白为什么如果只有一个仅包含纯虚方法的附加接口(interface)并且直接调用该类,那么对方法的调用会变慢。

Array<int, 1000> a;
a.Get(0); // Slow

ArrayWithoutInterface<int, 1000> awi;
awi.Get(0); // Fast

GCC 4.4.3 和 Clang 1.1 表现出相同的行为。

最佳答案

这种行为是意料之中的:你正在调用一个虚拟方法。无论您是直接调用它还是通过基类指针调用它,一开始并不相关:在这两种情况下,调用都必须通过虚函数表。

对于像 Get 这样的简单调用(它只是取消对数组单元格的引用,大概没有边界检查),这确实可以产生 4 倍的差异。

现在,一个好的编译器可以看到这里不需要添加间接寻址,因为对象的动态类型(以及方法调用目标)在编译时是已知的。我有点惊讶 GCC 显然没有对此进行优化(您是否使用 -O3 进行编译?)。话又说回来,这只是一种优化。

关于c++ - 接口(interface)开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4106223/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com