什么是 C++ 中的“翻译单元”?

Posted

技术标签:

【中文标题】什么是 C++ 中的“翻译单元”?【英文标题】:What is a "translation unit" in C++? 【发布时间】:2010-11-09 12:29:28 【问题描述】:

我当时正在阅读Scott Meyers 写的“Effective C++” 遇到了“翻译单元”这个词。

谁能给我解释一下:

    究竟是什么?

    在使用 C++ 编程时我应该何时考虑使用它?

    它只与 C++ 相关,还是可以与其他编程语言一起使用?

我可能已经在不知道这个词的情况下使用它......

【问题讨论】:

2.如果您已包含头文件,则您已经在使用翻译单元。它是一个用于参考的术语,而不是一个 c++ 结构。 【参考方案1】:

来自here: (wayback machine link)

根据standard C++ (wayback machine link) : 翻译单元是基本单元 在 C++ 中编译。它包括 单个源文件的内容, 加上任何头文件的内容 直接或间接包含在其中, 减去那些被忽略的行 使用条件预处理 声明。

单个翻译单元可以是 编译成目标文件,库, 或可执行程序。

翻译单元的概念是 在上下文中最常提到 单一定义规则,和 模板。

【讨论】:

该术语是否仅在 C/C++ 中使用? @dekuShrub 事实上,没有。例如,在 Rust 中,翻译单元是一个 crate,在 C++ 中,同样的东西将被称为整个库。这个术语本身是通用的,但它肯定是从 C 开始的。 新参考,大致说明了这个答案的内容:en.wikipedia.org/wiki/Translation_unit_(programming)【参考方案2】:

翻译单元在所有意图和目的上都是一个文件 (.c/.cpp),它完成后包含所有头文件。

http://msdn.microsoft.com/en-us/library/bxss3ska%28VS.80%29.aspx

【讨论】:

包括头文件。即使没有生成代码,编译器也会处理头文件。另请参阅 JeffH 的预处理器注释,“编译器看到的一切”的定义是一个很好的定义。 你可以编译以“.h”结尾的文件就好了。文件名根本不重要。内容是。如果 "foo.h" 的内容是 "int main() " 你可以编译它。 @GManNickG:“.h 文件通常不直接提供给编译器。” @JohannesSchaub-litb 我认为您的意思是链接,而不是编译。您可以编译任何文件,只要它是正确的 C/C++ 并定义了所有名称。编译头文件是没有用的,因为头文件的整个点都将被包含(读取复制)到源文件中,因此当您编译包含它的源文件时它们已经被编译。我猜你的意思是你不能从没有 main 函数的文件创建可执行文件。 链接现已失效/文档已停用。【参考方案3】:

很难明确回答的问题。 C++ 标准规定:

程序的文本保存在本国际标准中称为源文件的单元中。一个源文件 连同所有头文件(17.4.1.2)和源文件(16.2)通过 预处理指令#include,减去任何被跳过的任何源代码行 有条件的包含 (16.1) 预处理指令,称为翻译单元。 [注:一个C++ 程序不需要全部翻译 同时。 ]

因此,对于大多数意图和目的而言,翻译单元是单个 C++ 源文件以及它通过预处理器#include 机制包含的头文件或其他文件。

关于您的其他问题:

    什么时候应该考虑使用它 使用 C++ 编程时

您不能不使用它 - 翻译单元是 C++ 程序的基础。

    如果它只与 C++ 相关,或者它 可与其他编程一起使用 语言

其他语言也有类似的概念,但它们的语义会略有不同。例如,大多数其他语言不使用预处理器。

【讨论】:

我不知道这是否澄清。这可能是一个有点模糊的区域 - 例如,从我引用的标准段落中并不清楚允许预编译的头文件。 @GMan,这就是你必须非常小心单一定义规则的地方。如果您在包含该类之前在不同的翻译单元中包含一个具有略微不同定义的类,从而导致该类具有不同的代码,则会导致未定义的问题。 @GMan 注意标准使用的两个术语:“头文件”和“源文件”。 “header”仅用于标准库。某些代码包含的用户文件在标准中不称为“头文件”,而是称为“源文件”。标准不知道我们可怜的 c++ 程序员编造的“.h”和“.cpp”之间的区别:)【参考方案4】:

这本书说得很清楚。当 Meyers 提到“翻译单元”时,他指的是源代码文件。

【讨论】:

没有。如果他在谈论源代码,他会说源文件。翻译单元是通过编译源代码制成的。注意明显的区别。它是“翻译”的源代码。 @Dan:不,不是。翻译单元是包含后的源文件,可以编译,即编译前预处理器的输出。 事实上,不管 C++ 标准如何称呼它,“翻译单元”通常用于传达编译代码的单个“单元”的概念。事实上,根据微软编译器的说法,你直接链接“翻译单元”。 msdn.microsoft.com/en-us/library/vstudio/… 那么,我们是想成为“C++ 标准”的纳粹分子,还是想帮助人们与业内其他人交流?我知道这是一个 C++ 线程,所以我不会进入 xcode 所谓的 tu。或该术语的所有其他定义。 @Dan:翻译单元就是标准所说的。我并不真正关心随机编译器开发人员的意见。有趣的是,那个挖了将近五年前的帖子来吹毛求疵并告诉我我的定义是错误的人转过身来并称我为“语言纳粹”以纠正他的错误。是的,继续前进,你很累。【参考方案5】:

除了 ODR,翻译单元在未命名命名空间的定义中也很重要,它取代了“静态”的旧用法之一。

我想我仍然没有足够的积分在最佳答案下添加评论。

【讨论】:

【参考方案6】:

翻译单元是传递给编译器的代码。这通常意味着在 .c 文件上运行预处理器的输出。

【讨论】:

【参考方案7】:

C 和 C++ 程序由一个或多个源文件组成,每个源文件都包含程序的一些文本。源文件及其包含文件(使用 #include 预处理器指令包含的文件)但不包括由条件编译指令(如 #if)删除的代码部分,称为“翻译单元”。

【讨论】:

【参考方案8】:

根据MSDN:C 和C++ 程序由一个或多个源文件组成,每个源文件都包含程序的一些文本。源文件及其包含文件(使用 #include 预处理器指令包含的文件)但不包括由条件编译指令(如 #if)删除的代码部分,称为“翻译单元”。

【讨论】:

【参考方案9】:

每个 cpp/c(实现)文件都将被转换为一个翻译单元(即目标文件 (.obj)),cpp 文件中的标头将替换为标头文件中的实际文本。

【讨论】:

【参考方案10】:

正如其他人所说,翻译单元基本上是预处理后的源文件内容。它是语言语法中的最高产出;如果您正在编写 C 或 C++ 编译器,您只需要担心它。

【讨论】:

"如果您正在编写 C 或 C++ 编译器,您只需要担心它。"我不同意:程序员通常需要了解编译器在做什么。因此,例如,您需要知道什么是翻译单元,以便理解有效 C++ 中第 5 条中的一个重要观点:“在不同翻译单元中定义的非本地静态对象的相对初始化顺序是未定义的”。 【参考方案11】:

在我看来,“翻译单元”通常是一个“后预处理”源文件。您可以在此 MSDN 页面上获得更多详细信息。 http://msdn.microsoft.com/en-us/library/bxss3ska(v=vs.80).aspx

【讨论】:

以上是关于什么是 C++ 中的“翻译单元”?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 编译与翻译单元

在命名空间中定义并在多个翻译单元中使用的变量的链接

静态、全局和多个翻译单元

C++,是啥导致引用保存在内存中的方式不同

为啥模板类函数必须在同一个翻译单元中声明?

C ++内联方法实现[重复]