使用 template<int size> 比动态分配有啥好处?

Posted

技术标签:

【中文标题】使用 template<int size> 比动态分配有啥好处?【英文标题】:What the benefits by using the template<int size> than dynamic allocate?使用 template<int size> 比动态分配有什么好处? 【发布时间】:2019-04-30 02:21:43 【问题描述】:

我正在阅读 pbrt,它定义了一个类型:

template <int nSpectrumSamples>
class CoefficientSpectrum;
class RGBSpectrum : public CoefficientSpectrum<3> 
    using CoefficientSpectrum<3>::c;
typedef RGBSpectrum Spectrum;
// typedef SampledSpectrum Spectrum;

而作者说:

“我们没有编写系统,以便可以在运行时解决使用哪个 Spectrum 实现的选择;要切换到不同的表示,必须重新编译整个系统。这种设计的一个优点是许多各种 Spectrum 方法可以实现为可以由编译器内联的短函数,而不是作为必须通过相对较慢的虚方法调用机制调用的独立函数。内联这些常用的短函数可以给出性能大幅提升。”

1.为什么模板可以内联函数而普通方式不能?

2.为什么普通方式必须使用虚方式?

链接到整个头文件: https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.h

【问题讨论】:

C++ 支持静态(编译时)和动态(运行时)多态性。前者作为模板,后者作为具有虚拟成员函数的类。两者都有其优点/缺点。静态多态性必须在编译时解决(缺点),但不受虚函数运行时开销的影响(优点)。对于该库的作者来说,性能可能比运行时灵活性更重要,因此他们决定选择静态多态性。 还要注意动态分配与问题无关。 感谢您的注意,Max.Actually,我错过了报价的一部分。 >第二个优点是系统中保存 Spectrum 类型实例的结构可以直接保存它们,而不需要根据运行时选择的谱表示动态分配它们。 @Y.Lex 动态多态性通常通过基类指针实现,您可以在其中存储派生类的动态分配实例的地址。 【参考方案1】:

要内联函数调用,编译器必须知道 1. 调用了哪个函数,以及 2. 该函数的确切代码。 virtual 函数的全部目的是将调用哪个函数的选择推迟到运行时,因此编译器只能通过需要非常特殊情况的复杂优化技术才能获得上述信息1

模板和虚函数(即多态)都是编码抽象的工具。使用CoefficientSpectrum 的代码并不真正关心频谱的实现细节,只关心你可以例如将其与 RGB 相互转换——这就是它使用抽象的原因(以避免为每种光谱重复代码)。正如您在引用的评论中所解释的那样,在这里使用多态进行抽象意味着编译器很难优化代码,因为它从根本上将实现的选择推迟到运行时(这有时很有用,但在这里并不是绝对必要的)。通过要求在编译时选择实现,编译器可以轻松优化(即内联)代码。

1例如,一些编译器能够优化掉std::function 抽象,它通常使用多态来进行类型擦除。当然,这只有在所有必要信息都可用的情况下才有效。

【讨论】:

以上是关于使用 template<int size> 比动态分配有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

有条件的专业化

模板参数

大根堆(HEAP)模板

启用优化的g ++和clang ++的奇怪行为[重复]

Leetcode 455. Assign Cookies

<g:applyLayout /> 和 <g:render template /> 有啥区别