研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?

2023年就要过去,马上要跨如2024年。祝大家在新的一年,有个好收成。

一直以来不是很确定:

同样的的模板,在各个cpp分别出现,编译器要实现几份?

研究一下。

用命令行的编译方法,参考:

演练:在命令行上编译本机 C++ 程序 | Microsoft Learn

首先,启动vs的开发者控制台:

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第1张图片

 研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第2张图片

创建a.cpp,内容如下。

void fun1()
{
    int x=0;
    x++;
}

进行编译

(进编译成obj,如果不用选项/c,会进行link的动作,会报编译错误。加了/c,就只是编译)

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第3张图片

查看,发现生成了 a.obj文件,它的尺寸是1KB:

 用dumpbin查看符号

,注意,虽然fun1函数里用到了int类型的变量,但在dumpbin出来的时候,没有int的字样,因为它不是符号(symbol):

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第4张图片

 将a.cpp改一下,加入std::vector

用double实例化std::vector:

a.cpp

#include
void fun1()
{
    std::vector a;
    int x=0;
    x++;
}

重复刚才的编译命令:cl  /c /EHsc a.cpp

发现a.obj的大小变成了8KB:

 可以看出,模板的引入,对obj的个头影响。

看看符号,因为内容较多,所以输出到文本文件里:

 搜索double字样,有65个匹配,说明出现了一些用double实例化的一些函数(symbol)。也可以看到vector的出现:

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第5张图片

 创建b.cpp,内容和a.cpp一样

b.cpp

#include
void fun1()
{
    std::vector a;
    int x=0;
    x++;
}

然后对b.cpp进行编译:

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第6张图片

观察b.obj的大小,发现也是8KB大小

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第7张图片

compare一下a.obj和b.obj:

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第8张图片

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第9张图片 

发现,二进制应该是一致的。

这就说明了,对于每个cpp编译产生自己的obj文件,都会独自对模板进行实例化。这就是重复的内容。消耗了编译时间,增加了编译出来的obj的大小。

也可以同时对a.cpp和b.cpp进行编译,可以同时生成a.obj和b.obj:

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第10张图片

a.cpp
#include
void fun1()
{
    std::vector a;
    int x=0;
    x++;
}

b.cpp
#include
void fun2()
{
    std::vector a;
    int x=0;
    x++;
}

hello.cpp
#include 
using namespace std;
int main()
{
    cout << "Hello, world, from Visual C++!" << endl;
}

 编译出hello.exe

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第11张图片

hello.exe文件的大小是189KB,比a.obj、b.obj和hello.obj加起来都大

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第12张图片

各个obj里的重复的symbol会不会合并起来

分别在a.cpp和b.cpp里出现的std::vector在最后link的时候,应该是被合并成了一份。但这个例子说明不了。

实际项目说明了会合并

我们项目里的一个例子可以说明:

obj加起来超过2G,最后生成的dll只有12MB。(debug版)

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?_第13张图片

你可能感兴趣的:(算法)