2011-03-25 60 views
6

我可以理解它是如何工作的,如果他们内联。但如果他们不是,它是如何工作的?所有的目标文件都得到自己的副本,例如函数模板呢?模板如何工作,它们是否总是内联?

+0

这些模板用于生成代码。如果您使用模板,则会生成并使用类/函数。编译器可以使用相同的参数删除多个模板实例,但不能保证。我没有看到内联的链接。 – knivil 2011-03-25 10:46:45

回答

4

模板将在inline的标准含义,内联这与“一个定义规则”更有关系,而不是实际的代码内联。也就是说,如果模板函数定义在多个翻译单元中,链接器不会投诉,它只会选择一个(注意:随机一个,如果您在不同的翻译单元中提供不同模板定义,则当前编译器不会投诉! )并保留在最终的二进制文件中。

现在,与所有其他inline函数一样,编译器可以决定实际避免函数调用并在调用位置内联函数是一个好主意,或者可能会确定它不是这样一个好东西想法(大功能,一些编译器不嵌套函数嵌套循环......无论原因),然后它不会执行实际的代码内联。

+0

而编译器可能决定“内联”未声明为“inline”的函数。当使用'gcc'时,我注意到这个函数没有外部链接。 – Raedwald 2011-03-25 13:02:43

1

它取决于实现。

但通常,是的,每个对象文件都会获取它们使用的每个扩展函数的副本。 然后链接程序在链接时注意到这一点,并确保函数中只有一个副本被放入最终的可执行文件中

2

取决于编译器,但是我看过的每一个都创建了一个函数,然后可以调用使用替代模板参数来生成每个变量的代码。 (他们是在一种特殊的方式但是装饰,以防止其他问题)

template <typename T> T Max(T a, T b) 
{ 
    return a > b ? a : b; 
} 

时为Max<int>Max<float>调用,而不是内联,编译器生成:

一个非常简单的例子

然后
int Max(int a, int b) 
{ 
    return a > b ? a : b; 
} 

float Max(float a, float b) 
{ 
    return a > b ? a : b; 
} 

这是停留在对象的开始,然后引用,那么同样是对一些内联(在MSVC)

2

做得太它依靠。一些比较流行的实现是 在每个对象文件 中生成实例化代码的副本,其触发实例化,并且计数连接器到 除了一个之外全部丢弃。其他编译器使用某种 存储库,其中实例化被存储;如果 实例化已经存在,编译器不会打扰 重新生成它。此解决方案速度更快,并且使用比第一种解决方案少的磁盘,但是 也很难更正。 (编译器必须产生一个新的实例 不仅如果不存在,但如果任何 实例取决于文件的发生了变化。)

0

模板是真的非常非常先进的宏(#定义)

参数是在编译时与传递的值代替。真的很棒的概念,也非常好。

+0

宏不应该与模板混在一起,并且已经混淆了它们的概念:宏在第一个转换步骤中正确扩展,即它们可以生成要传递给C++分析器的标记。这是不可能的模板。 – 2011-12-19 13:12:01

0

模板对自己来说是一种完整的语言。他们是图灵完整的,但“程序”在编译时运行。它们是在编译时替换对象类型的代码工厂,并在编译时组装类,函数等。所以你可以把它看作一种类型安全的,C++兼容的大规模预处理语言。执行的结果输出是纯粹的C++代码,然后编译器可以像处理所有其他代码一样处理它。

编译器通常忽略内联,因为很少有程序员可以真正知道什么时候最好,哪些还没有离开汇编。

相关问题