如果我有一个C ++模板,我有两个选择(没有 export 关键字)来链接它们:
包含内联的包含模型 - 即包含定义以及.h文件中的声明。这内联所有功能并创建一个大单元(虽然它很懒)
没有内联的包含模型 - 例如包含此.h文件的内容:
代码:
// templateinstantiations.cpp
#include "array.cpp"
template class array <int, 50>; // explicit instantiation
每次我想使用模板,并小心显式实例化我需要的每一种类型(这可能很无聊,难以维护)
我的问题是:我知道过度内联函数可能会导致内存抖动和性能损失。此外,在上述两种情况下,编译时间似乎都很大。第一种和第二种方法之间的权衡是什么?是否有一个标准来选择第一个或第二个,或者我只需要尝试它们并“时间”它们?
答案 0 :(得分:1)
这个问题不是关于模板,而是关于内联,我想。出于运行时性能的目的,编译器在大多数情况下可能做出正确的选择:如果它可以看到函数太大而无法从内联中受益,则可能会生成任何内联函数的非内联版本,独立该函数是否是模板。每个翻译单元将创建自己的函数版本,链接器将选择一个使用(并且,希望丢弃其他未使用的副本,但它是否确实这取决于链接器和目标文件格式)。
当查看模板代码与其调用的函数(可能是模板本身)之间的各种交互时,与模板的交互就出现了:当强制代码不被内联时,编译器没有机会避免代码的开销。功能调用。模板使用的抽象通常是非常简单的函数,例如“递增迭代器”和“取消引用迭代器”映射到底层指针操作,由于函数调用开销和丢失优化机会,创建函数调用会变得相当昂贵。 。但是,编译器实际上可以看到这一点并在许多情况下做出正确的选择。
那就是说,我非常喜欢为某些模板创建显式实例化。例如,从头中删除IOStreams库的某些部分并在库中显式实例化它会对编译时产生巨大影响,尤其是在打开优化时:为整数调用一个简单的输出函数会导致大量模板被实例化。将此代码放入其自己的文件并使用适当的优化选项进行编译可能不会对性能产生太大影响,但它确实会对编译时间产生重大影响。但这可能会对性能产生间接影响:您可以使用库测试代码性能的更多迭代次数。
答案 1 :(得分:0)
即使你明确地将一个函数声明为inline
,也不能保证C ++使它成为inline
,所以你认为在头文件中实现一个模板会强制inline
实现并导致一些问题?
在几乎所有情况下,您都不需要第二种情况,尽管您可以这样做,但不需要避免inline
问题