我在 MSVC 编译器中遇到了一些奇怪的事情。
它将函数模板定义放在汇编中,而优化消除了对它们的需要。看起来 Clang 和 GCC 完全成功地删除了函数定义,但 MSVC 却没有。
可以修复吗?
主要.cpp:
#include <iostream>
template <int n> int value() noexcept
{
return n;
}
int main()
{
return value<5>() + value<10>();
}
Run Code Online (Sandbox Code Playgroud)
集会:
int value<5>(void) PROC ; value<5>, COMDAT
mov eax, 5
ret 0
int value<5>(void) ENDP ; value<5>
int value<10>(void) PROC ; value<10>, COMDAT
mov eax, 10
ret 0
int value<10>(void) ENDP ; value<10>
main PROC ; COMDAT
mov eax, 15
ret 0
main ENDP
Run Code Online (Sandbox Code Playgroud)
交换机/FA为每个翻译单元生成列表文件。由于这是在链接阶段之前,MSVC 无法确定程序中其他任何地方是否需要这两个函数,因此仍然包含在生成的 .asm 文件中(注意:这可能是 MS 方面的简单性,因为它可以将模板视为生成的 .obj 文件中的常规函数,尽管实际上没有实际需要将它们存储在 .obj 文件中,正如 user17732522 在评论中指出的那样)。
在链接过程中,MSVC 确定这些函数实际上在其他任何地方都没有实际使用/需要,因此可以被消除(即使它们在其他地方使用,因为结果可以在编译时确定,它们仍然会被消除)编译后的可执行文件。
为了查看最终编译的可执行文件中的内容,您可以通过反汇编程序查看可执行文件。使用 MSVC 执行此操作的示例是在 main 函数中放置一个断点,运行它,然后当断点被命中时,右键单击并“查看反汇编”。在这里,您将看到这两个函数不再存在。
您还可以使用选项生成Mapfile /MAP,这也显示它不存在。
如果我正确地阅读文档,似乎那些 MS 选择包含模板类和函数的显式实例化,因为它在创建库时“很有用”。但未实例化的模板不会放入 obj 文件中。