C ++头文件如何工作?

时间:2010-05-16 14:57:46

标签: c++ header-files

当我在C ++程序中包含头文件中的某些函数时,整个头文件代码是否被复制到最终的可执行文件中,或者只生成特定函数的机器代码。例如,如果我从C ++中的std::sort标头调用<algorithm>,那么机器代码是仅针对sort()函数或整个<algorithm>头文件生成的。

我认为Stack Overflow上存在一个类似的问题,但我已经尽力找到它(我曾经看了一次,但丢失了链接)。如果你能指出我的话,那就太棒了。

4 个答案:

答案 0 :(得分:11)

你在这里混合了两个不同的问题:

  1. 头文件,由预处理器处理
  2. 通过C ++链接器选择性地链接代码
  3. 头文件

    这些只是由预处理器逐字复制到include的位置。 algorithm时,.cpp的所有代码都会复制到#include <algorithm>文件中。

    选择性链接

    大多数现代链接器都不会链接到您的应用程序中未调用的函数。即编写一个函数foo并且永远不会调用它 - 它的代码不会进入可执行文件。因此,如果您#include <algorithm>并且仅使用sort,则会发生以下情况:

    • 预处理器将整个algorithm文件推送到源文件
    • 您只需拨打sort
    • 链接分析此内容并仅将sort的源(以及它调用的函数,如果有的话)添加到可执行文件中。其他算法的代码没有添加

    也就是说,C ++模板使问题进一步复杂化。这里需要解释一个复杂的问题,但简而言之 - 编译器会为您实际使用的所有类型扩展模板。因此,如果vector intvector string,编译器将为代码中的vector类生成两个代码的副本。由于您正在使用它(否则编译器不会生成它),链接器也会将其放入可执行文件中。

答案 1 :(得分:3)

实际上,整个文件被复制到.cpp文件中,它依赖于编译器/链接器,如果它只选择“需要”的功能,或者所有这些功能。

一般来说,简化摘要:

  • 调试配置意味着在所有非模板函数中进行编译,
  • 发布配置剥离所有不需要的功能。

另外,它取决于属性 - &gt;声明用于导出的函数将永远不会被剥离。 另一方面,模板函数变体在使用时会“生成”,因此只编译您明确使用的变体。

编辑:未生成头文件代码,但在大多数情况下是手写的。

答案 2 :(得分:1)

如果您在源代码中#include一个头文件,就好像该头文件中的文本是用#include预处理器指令代替的。

通常标头包含声明,即有关库内部内容的信息。这样编译器允许您调用代码存在于当前编译单元之外的事物(例如,包含头部的.cpp文件)。当程序链接到可以运行的可执行文件时,链接器通常根据程序实际使用的内容决定要包含的内容。库也可以动态链接,这意味着可执行文件实际上不包含库代码,但库在运行时链接。

答案 3 :(得分:0)

这取决于编译器。今天大多数编译器都进行流量分析以修剪掉未调用的函数。 http://en.wikipedia.org/wiki/Data-flow_analysis