0

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

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

  • 没有内联的包含模型 - 即包含此 .h 文件的内容:

代码:

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

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

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

4

2 回答 2

1

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

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

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

于 2012-10-06T15:18:34.667 回答
0

即使您显式声明了一个函数,因为inline不能保证 C++ 会成功inline,那么您如何认为在标头中实现一个模板会强制inline实现并给您带来一些问题?

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

于 2012-10-06T15:16:04.600 回答