C++ 模板和可执行文件
与没有模板的代码相比,编译并链接到PE中的模板代码的大小是否会增加。我认为使用的每个模板实例都是有序打包的,因此如果需要更快的速度,它将输出匹配C++ 模板和可执行文件,c++,templates,C++,Templates,与没有模板的代码相比,编译并链接到PE中的模板代码的大小是否会增加。我认为使用的每个模板实例都是有序打包的,因此如果需要更快的速度,它将输出匹配 很抱歉,我对模板了解不多 C++的工作原理是: 你为你使用的东西付费 模板代码仅为您使用/实例化的代码创建二进制文件 仅仅因为您是根据标准库进行编译的,标准库有数百个STL容器,这并不意味着您的目标代码包含所有STL容器,它只包含您使用的STL容器 模板实现编译时多态性。对于使用不同数据类型执行的每个实例化,都会创建模板化函数的副本,对于模板化类也是如
很抱歉,我对模板了解不多 C++的工作原理是:
你为你使用的东西付费
模板代码仅为您使用/实例化的代码创建二进制文件 仅仅因为您是根据标准库进行编译的,标准库有数百个STL容器,这并不意味着您的目标代码包含所有STL容器,它只包含您使用的STL容器
模板实现编译时多态性。对于使用不同数据类型执行的每个实例化,都会创建模板化函数的副本,对于模板化类也是如此。进一步编译此代码以创建二进制文件。因此,二进制文件的大小不会比没有模板的代码产生的大小大。模板本身根本不占用任何空间。它是该模板的实例化。一旦将模板与类型参数一起使用-
MyClass mc
,它就会被实例化。您使用的每个类型都会创建一个实例化,因此MyClass mc2
不会导致另一个实例化,而是使用现有的实例化
所以这实际上取决于模板使用了多少类型。但这与使用不同的非模板类没有什么不同,这也会增加代码的大小。底线-我不担心。除了@Als和@eran给出的答案外:
编译器和链接器将共同工作,找出给定类/函数的两种或不同数据类型的相同代码,如果他们找到相似的代码,即不依赖于数据类型,他们可能会创建该代码的一个副本。代码可能是类的方法、某些函数或方法/函数的某个部分。谢谢,这意味着该类型被忽略,不是吗?@Baby Dolphin:这很重要,每个类型都会生成一个模板函数/类的副本,请检查更新的答案。@Baby-另一方面,如果你没有模板,你将不得不为每种类型自己编写一次代码。但是如果你在多个翻译单元中说
MyClass
,会怎么样?会有重复的代码吗?这就是LTO发挥作用的地方吗?不,实现必须删除重复项(使用未指定的魔法)。LTO更多的是关于跨文件边界优化。@宝贝,LTO是。未指定的魔法指的是链接器删除重复实例化的方式,如果它们存在于不同的编译单元上-如果两个cpp文件中都有MC
,模板会在两个cpp文件上都实例化吗?如果是这样的话,两者是否都存在于最终的exe中,与我上面写的内容相矛盾?后者的答案当然不是……:)必须消除重复的实例化,但如何消除取决于编译器的实现。@eran:不是这样的。它们可以被消除,但不需要。唯一的要求是指向同一方法的指针比较相等。事实上,使用内联时,将存在多个副本,甚至可能只有一个TU。@MSalters:I认为eran
指的是符号不能在结果库/可执行文件中复制的事实。内联将复制代码,但不会复制函数/类。谢谢你I’我想多问一点,但我现在困了。现在是3点50分,我一整天都没睡,否则我会生病的。几个小时后再见,至少我读到的是错误的。如果void MC::foo()
与void MC::bar()
和void MC::baz()
相同,则链接器必须确保&MC::foo!=&MC::条形码
。但由于无法比较void MC::*(void)
和void MC::*(void)
指针,它可能会消除void MC::baz()
。你不能比较合法的指针并注意到这一点。我并没有说两个函数是否相同。我说过,如果同一函数的实现,对于两个或多个数据类型是相同的(或部分),那么编译器/链接器可以使用相同的代码段,而不是为相同的代码段进行冗余汇编。