模板如何工作,它们总是内联吗?
如果它们是内联的,我可以理解它是如何工作的。但如果不是,它是如何运作的呢?无论如何,所有目标文件都会获得自己的副本(例如函数模板)吗?
I can understand how it work if they are inlined. But if they are not, how does it work? does all object files get their own copy of for example the function template anyway?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
模板将以
内联
的标准含义进行内联,这与单一定义规则更相关,而不是与实际的代码内联相关。也就是说,如果模板函数在多个翻译单元中定义,链接器不会抱怨,它只会选择一个(注意:随机一个,如果您在不同的翻译单元中提供不同的模板定义,当前编译器不会抱怨! )并将其保留在最终的二进制文件中。现在,与所有其他内联函数一样,编译器可以决定实际上避免函数调用并在调用位置内联函数是一个好主意,或者它可能确定它不是这是一个好主意(大函数,一些编译器不使用嵌套循环内联函数......无论什么原因),然后它不会执行实际的代码内联。
Templates will be inlined in the standard meaning of
inline
, which is more related to the One Definition Rule than to actual code inlining. That is, the linker will not complain if the template functions are defined in more than one translation unit, it will just pick one (beware: random one, current compilers do not complain if you provide different definitions of the template in different translation units!) and leave that in the final binary.Now, as with all other
inline
functions, the compiler can decide that it is a good idea to actually avoid the function call and inline the function at the place of call, or it might determine that it is not such a good idea (big function, some compilers don't inline functions with nested loops... whatever the reason) and then it will not perform the actual code inlining.取决于编译器,但我看过的每个函数都会创建一个函数,然后可以使用替换的模板参数调用该函数来生成每个变体的代码。
作为一个(非常)简单的示例:
当作为
Max
和Max
调用并且未内联时,编译器会生成(但是它们以特殊方式装饰) ,以防止其他问题):然后将其固定在对象的开头,然后引用,然后对某些内联也执行相同的操作(在 MSVC 中)
Depends on the compiler, but every one I've looked at creates a function that is then callable using the substitued template parameters to generate the code for each varient.
as a (very) simple example:
when invoked as
Max<int>
andMax<float>
and not inlined, the compiler generates (they are decorated in a special way however, to prevent other problems):This is then stuck at the start of the object and then referenced, then same is done for some inlines too (in MSVC)
这取决于。一些更流行的实现确实
在每个目标文件中生成实例化代码的副本
这会触发实例化,并依靠链接器来
扔掉除了一个以外的所有东西。其他编译器使用某种
存储库,存储实例的地方;如果
实例化已经存在,编译器不会打扰
重新生成它。该解决方案速度明显更快并且使用
比第一个解决方案占用的磁盘更少,但也更难
做对了。 (编译器必须生成一个新的实例化
不仅如果其中一个文件不存在,而且如果其中任何一个文件存在
实例化取决于已更改。)
It depends. Some of the more popular implementations do
generate a copy of the instantiation code in each object file
which triggers an instantiation, and count on the linker to
throw out all but one. Other compilers use some sort of
repository, where instantiations are stored; if the
instantiation is already present, the compiler doesn't bother
regenerating it. This solution is significantly faster and uses
less disk than the first solution, but it's also a lot harder to
get right. (The compiler has to generate a new instantiation
not only if one isn't present, but if any of the files the
instantiation depends on have changed.)
它依赖于实现。
但通常情况下,是的,每个目标文件都会获得它们使用的每个扩展函数的副本。
然后链接器在链接时注意到这一点并确保只有该函数的一个副本放入最终的可执行文件中
it's implementation dependent.
But commononly, yes each object file gets a copy of each expanded function they use.
And then the linker notices this at link time and ensures that only one copy of the function gets put in the final executable file
模板本身就是一种完整的语言。它们是图灵完备的,但“程序”在编译时运行。它们是代码工厂,在编译时替换对象类型并在编译时组装类、函数等。因此,您可以将其视为类型安全、与 C++ 兼容的大规模预处理语言。执行的结果输出是纯 C++ 代码,然后编译器可以像处理其他任何事情一样处理它。
编译器通常会忽略内联,因为很少有程序员能够真正知道什么时候内联是最好的,而那些知道内联的人还没有离开汇编。
Templates are a complete language unto themselves. They are Turing complete, but the "program" runs at compile time. They are code factories that replace the object type at compile time and assemble classes, functions, etc. at compile time. So you can think of it as a type safe, C++ compatible massive preprocessing language. The resulting output of the execution is pure C++ code that can then be treated by the compiler the same as it does everything else.
Compilers generally ignore inline as very few programmers can really know when it's best and those who do have not left assembly.
模板实际上是非常非常先进的 MACROS (#define)
参数在编译时用传递的值替换。确实很棒的概念,而且实施得很好。
Templates are really very very advanced MACROS (#define)
parameters are replaced at compile time with the passed values. Really great concept and also implemented very wel.