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

2023-12-31 22:25:33

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

一直以来不是很确定:

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

研究一下。

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

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

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

?

创建a.cpp,内容如下。

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

进行编译

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

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

?用dumpbin查看符号

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

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

用double实例化std::vector:

a.cpp

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

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

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

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

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

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

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

b.cpp

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

然后对b.cpp进行编译:

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

compare一下a.obj和b.obj:

?

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

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

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

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

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

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

?编译出hello.exe

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

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

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

实际项目说明了会合并

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

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

文章来源:https://blog.csdn.net/tumu_C/article/details/135319534
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。