C++模板性能包含模型和内联模型

C++ Template performance inclusion model and inline model

本文关键字:模型 包含 性能 C++      更新时间:2023-10-16

如果我有C++模板,我有两个选择(没有export关键字)来链接它们:

  • 具有内联的包含模型,即在.h文件中包含定义和声明。这将内联所有函数并创建一个大单元(尽管它很懒)

  • 没有内联的包含模型,比如包含这个.h文件:

代码:

// templateinstantiations.cpp
#include "array.cpp"
template class array <int, 50>; // explicit instantiation

每次我想使用模板时,都要小心地显式实例化我需要的每一种类型(这可能很无聊,很难维护)

我的问题是:我知道过度内联函数可能会导致内存抖动和性能损失。。此外,在上述两种情况下,编译时间似乎都很长。。第一种方法和第二种方法之间的折衷是什么?有没有标准可以选择第一个而不是第二个,或者我只需要尝试一下并"计时"一下?

我认为,这个问题实际上不是关于模板,而是关于内联。出于运行时性能的目的,编译器在大多数情况下可能会做出正确的选择:如果它发现一个函数太大,无法从内联中获益,那么它很可能会生成任何内联函数的非内联版本,而与该函数是否为模板无关。每个翻译单元都将创建自己的函数版本,链接器将选择一个版本来使用(并希望丢弃其他未使用的副本,但它是否真的这样做取决于链接器和对象文件格式)。

当查看模板代码和它调用的函数(可能是模板本身)之间的各种交互时,就会出现与模板的交互:当强制代码不内联时,编译器没有机会避免函数调用的开销。模板使用的抽象通常是非常简单的函数,例如,映射到底层指针操作的"增量迭代器"answers"取消引用迭代器",由于函数调用开销和失去优化机会,创建函数调用可能会变得相当昂贵。然而,编译器实际上可以看穿这一点,并在许多情况下做出正确的选择。

也就是说,我非常喜欢为某些模板创建显式实例化。例如,从标头中删除IOStreams库的某些部分并在库中显式实例化它会对编译时间产生巨大影响,尤其是在启用优化时:为整数调用简单的输出函数会导致大量模板被实例化。将这些代码放入自己的文件中,并使用适当的优化选项进行编译,可能不会对性能产生太大影响,但它确实会对编译时间产生重大影响。不过,这可能会对性能产生间接影响:您可以使用库进行更多的迭代来测试代码的性能。

即使您显式地将函数声明为inline,也不能保证C++使其成为inline,那么您认为在头中实现模板会强制实现inline并给您带来一些问题吗?

在几乎所有的情况下,你都不需要第二种情况,尽管你可以这样做,但不需要避免inline问题