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

What is a "translation unit" in C++?

提问人:Harry 提问时间:7/10/2009 最后编辑:ManuelHarry 更新时间:10/4/2023 访问量:105232

问:

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

有人可以给我解释以下内容吗:

  1. 它到底是什么?

  2. 在使用 C++ 编程时,我应该考虑在什么时候使用它?

  3. 是仅使用 C++,还是可以与其他编程语言一起使用?

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

C C++-常见问题

评论

1赞 talekeDskobeDa 9/19/2019
2. 如果您包含头文件,则您已经在使用翻译单元。这是一个用于参考的术语,而不是 c++ 构造本身

答:

90赞 Ana Betts 7/10/2009 #1

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

http://web.archive.org/web/20091213073754/http://msdn.microsoft.com/en-us/library/bxss3ska(VS.80).aspx

评论

3赞 Marco van de Voort 7/10/2009
包括头文件。头文件由编译器处理,即使未生成任何代码也是如此。另请参阅 JeffH 的预处理器注释,“编译器看到的一切”的定义是一个很好的定义。
17赞 Johannes Schaub - litb 7/10/2009
您可以编译以“.h”结尾的文件。文件名根本不重要。内容是。如果 “foo.h” 的内容是 “int main() { }”,则可以编译它。
0赞 GManNickG 2/5/2013
@LightnessRacesinOrbit:是的,我想说的是,直接将标头编译为 TU,而不是通过包含间接将其编译为 TU 是非正统的。删除了第一条评论,因为这是完全错误的,保留了第二条评论,为我们的新评论提供了背景信息。
1赞 Lightness Races in Orbit 2/5/2013
@GManNickG:“.h 文件通常不会直接提供给编译器”怎么样?
2赞 pooya13 3/28/2019
@JohannesSchaub升,我认为你的意思是链接,而不是编译。您可以编译任何文件,只要它是定义了所有名称的正确 C/C++。编译头文件是没有用的,因为头文件的整个要点是包含(读取复制)到源文件中,因此在编译包含它的源文件时,它们已经在编译中了。我想你的意思是你不能从一个没有 main 函数的文件创建可执行文件。
7赞 Ed S. 7/10/2009 #2

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

评论

1赞 Dan 2/22/2014
不。如果他谈论的是源代码,他会说源文件。翻译单元是通过编译源代码来制作的。请注意明显的差异。它是“翻译”的源代码。
4赞 Ed S. 2/22/2014
@Dan:不,不是。翻译单元是包含之后的源文件,可以编译,即编译前预处理器的输出。
1赞 Dan 2/22/2014
事实上,尽管 C++ 标准称之为“翻译单元”,但“翻译单元”通常用于传达编译代码的单个“单元”的概念。事实上,根据Microsoft编译器的人的说法,你直接链接“翻译单元”。msdn.microsoft.com/en-us/library/vstudio/......
1赞 Dan 2/22/2014
那么,我们是试图成为“C++标准”的纳粹分子,还是试图帮助人们与行业其他成员进行交流?我知道这是一个 C++ 线程,所以我不会进入 xcode 所说的 tu。或该术语的所有其他定义。
4赞 Ed S. 2/23/2014
@Dan:翻译单元就是标准所称的。我并不真正关心随机编译器开发人员的意见。有趣的是,那个挖出近五年前的帖子吹毛求疵并告诉我我的定义是错误的家伙转过身来,称我为“语言纳粹”来纠正他的定义。是的,继续前进,你很累。
341赞 JeffH 7/10/2009 #3

这里:(wayback machine link)

根据标准 C++回溯机链接): 翻译单元是基本单元 在 C++ 中编译。它包括 单个源文件的内容, 以及任何头文件的内容 直接或间接包含在其中, 减去那些被忽略的行 使用条件预处理 语句。

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

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

评论

23赞 dekuShrub 4/18/2018
该术语仅在 C/C++ 中使用吗?
6赞 12/7/2019
@dekuShrub事实上,没有。例如,在 Rust 中,翻译单元是一个板条箱,在 C++ 中,同样的东西被称为整个库。这个术语本身是通用的,但它肯定是从 C 开始的。
2赞 Gabriel Staples 5/12/2020
新的参考资料大致说明了这个答案所说的内容:en.wikipedia.org/wiki/Translation_unit_(编程)
0赞 425nesp 4/14/2022
是否可以在编译之前查看翻译单元的内容?
0赞 Dai 10/15/2022
@425nesp GCC 以前有这个选项,但最近被删除了。其他编译器/工具也有类似的选项: stackoverflow.com/q/39140779/159145-fdump-lang-raw
5赞 sigjuice 7/10/2009 #4

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

0赞 yesraaj 7/10/2009 #5

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

37赞 anon 7/10/2009 #6

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

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

因此,对于大多数意图和目的,翻译单元是源文件及其包含的头 #include 机制的单个C++。

关于您的其他问题:

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

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

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

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

评论

1赞 7/10/2009
我不知道这是否澄清了。这可能是一个有点模糊的领域 - 例如,从我引用的标准段落中并不清楚是否允许预编译标头。
1赞 Matt Price 7/10/2009
@GMan,这就是你必须非常小心一个定义规则的地方。如果在包含该类之前将某个类包含在定义略有不同的不同转换单元中,则会导致该类具有不同的代码,这将导致未定义的问题。
6赞 Johannes Schaub - litb 7/10/2009
@GMan注意标准使用的两个术语:“头文件”和“源文件”。“header”仅用于标准库。某些代码包含的用户文件在标准中不称为“标头”,而是称为“源文件”。标准不知道“.h”和“.cpp”之间的区别,我们这些可怜的 c++ 程序员编造了:)
0赞 John Bode 7/10/2009 #7

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

评论

1赞 Channing Moore 8/7/2015
“如果你正在编写C或C++编译器,你只需要担心它。我不同意:程序员通常需要了解编译器在做什么。因此,例如,您需要知道翻译单元是什么,以便理解有效 C++ 中项目 #5 中的一个重要点:“在不同翻译单元中定义的非局部静态对象初始化的相对顺序是未定义的”。
1赞 rahul 10/31/2009 #8

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

6赞 Allan Stokes 11/11/2011 #9

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

0赞 Yang 7/30/2013 #10

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

3赞 ganesh marmat 3/18/2015 #11

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