[英]How does forward declaration save compile time?
If you read online then there is plenty of claims that in C++ if you use forward declaration then it saves your compile time.如果您在线阅读,那么在 C++ 中有很多声明,如果您使用前向声明,那么它可以节省您的编译时间。 The usual theory is that since
#include
means mere text replacement if I use forward declaration, then my compiler doesn't need to parse the header and possibly compile it, so it saves time.通常的理论是,如果我使用前向声明,
#include
意味着仅仅是文本替换,那么我的编译器不需要解析 header 并可能编译它,所以它节省了时间。 I found this claim hard to believe because consider I usually see code like this:我发现这种说法很难相信,因为考虑到我通常会看到这样的代码:
// B.h
class A;
class B {
public:
void doSomething(A& a);
}
In this case, yeah, we don't need to include Ah
in Bh
as we forward declared it, but the problem is that in B.cpp
eventually, we need a full type A
to use its methods and data members.在这种情况下,是的,我们不需要在
Bh
中包含Ah
,因为我们转发声明它,但问题是最终在B.cpp
中,我们需要一个完整的类型A
来使用它的方法和数据成员。 So I found in nearly all cases, we need to include Bh
in B.cpp
.所以我发现几乎在所有情况下,我们都需要在
B.cpp
中包含Bh
。
So how does forward declaration actually save compile time?那么前向声明实际上是如何节省编译时间的呢? I see people with benchmarks to prove that if they use forward declaration instead of
#include
s, the compile time actually goes down, so there must be something I do not understand here...我看到有人用基准来证明如果他们使用前向声明而不是
#include
s,编译时间实际上会下降,所以这里肯定有我不明白的东西......
I know saving compile time is not the sole purpose of forward declaration, I understand it has other purposes.我知道节省编译时间不是前向声明的唯一目的,我知道它还有其他目的。 I just want to understand why some people claim it can save compile time.
我只是想了解为什么有些人声称它可以节省编译时间。
the problem is that in
B.cpp
eventually, we need a full typeA
to use its methods and data members.问题是最终在
B.cpp
中,我们需要一个完整的类型A
来使用它的方法和数据成员。
Yes, that is a typical pattern.是的,这是一个典型的模式。 Forward declare a class (eg
A
) in a header (eg Bh
), then in the source code corresponding to that header ( B.cpp
), include the header for the forward-declared class ( Ah
). Forward declare a class (eg
A
) in a header (eg Bh
), then in the source code corresponding to that header ( B.cpp
), include the header for the forward-declared class ( Ah
).
So I found in nearly all cases, we need to include
Bh
inB.cpp
.所以我发现几乎在所有情况下,我们都需要在
B.cpp
中包含Bh
。
Correct, forward declarations do not save time when compiling the corresponding source code .正确的前向声明在编译相应的源代码时不会节省时间。 The savings come when compiling other source code that uses
B
.编译使用
B
的其他源代码时可以节省。 For example:例如:
other.cpp其他.cpp
#include "B.h"
// Do stuff with `B` objects.
// Make no use of `A` objects.
Assume this file does not need definitions from Ah
.假设这个文件不需要
Ah
的定义。 This is where the savings come in. When compiling other.cpp
, if Bh
uses a forward declaration of A
, there is no need to process Ah
.这就是节省的地方。编译
other.cpp
时,如果Bh
使用A
的前向声明,则无需处理Ah
。 Nor is there a need to process the headers that Ah
itself includes, and so on.也不需要处理
Ah
本身包含的标头,等等。 Now multiply this effect by the number of files that include Bh
, either directly or indirectly.现在将此效果乘以直接或间接包含
Bh
的文件数。
Note that there is a compounding effect here.请注意,这里有一个复合效应。 The number of "headers that
Ah
itself includes" and of "files that include Bh
" would be the numbers before replacing any #include
statements with forward declarations. “
Ah
本身包含的标题”和“包含Bh
的文件”的数量将是在用前向声明替换任何#include
语句之前的数字。 (Once you start making these replacements, the numbers come down.) (一旦你开始进行这些替换,数字就会下降。)
How much of an effect?有多大的作用? Not as much as there used to be.
没有以前那么多了。 Still, as long as we're talking theoretically, even the smallest savings is still a savings.
尽管如此,只要我们在理论上谈论,即使是最小的储蓄仍然是储蓄。
Instead of raw compile times (build everything), I think a better focus would be on rebuild times.而不是原始编译时间(构建所有内容),我认为更好地关注重建时间。 That is, the time it takes to compile just the files affected by a change you made.
也就是说,仅编译受您所做更改影响的文件所需的时间。
Suppose there are ten files that rely on Bh
but not on Ah
.假设有十个文件依赖于
Bh
但不依赖于Ah
。 If Bh
were to include Ah
, then those ten files would be affected by changes to Ah
.如果
Bh
包含Ah
,那么这十个文件将受到Ah
更改的影响。 If Bh
were instead to forward declare A
, then those files would not be affected by changes to Ah
, reducing the time to rebuild after those changes.如果
Bh
改为转发声明A
,那么这些文件将不会受到Ah
更改的影响,从而减少了这些更改后的重建时间。
Now suppose there is another class, call it B2
, that also has the option to forward declare A
instead of including the header.现在假设还有另一个 class,称为
B2
,它还可以选择转发声明A
而不是包括 header。 Maybe there are another ten files that depend on B2
but not on B
and not on A
.也许还有另外十个文件依赖于
B2
但不依赖于B
而不是依赖于A
。 Now there are a twenty files that do not need to be re-compiled after changes to A
.现在有二十个文件在更改
A
后不需要重新编译。
But why stop there?但为什么要停在那里? Let's add
B3
through B10
to the mix.让我们将
B3
到B10
添加到混合物中。 Now there are a hundred files that do not need to be re-compiled after changes to A
.现在有一百个文件在更改
A
后不需要重新编译。
Add another layer.添加另一层。 Suppose there is a
C.h
that has the option to forward declare B
instead of including Bh
.假设有一个
C.h
可以选择转发声明B
而不是包括Bh
。 By using a forward declarations, changes to Ah
no longer require re-compiling the ten files that use C.h
.通过使用前向声明,对
Ah
的更改不再需要重新编译使用C.h
的十个文件。 And, of course, we'll assume there are ten such files for each of B
through B10
.而且,当然,我们假设
B
到B10
中的每一个都有十个这样的文件。 Now we're up to 10*10*10
files that do not need to be recompiled when Ah
changes.现在我们最多有
10*10*10
文件,当Ah
发生变化时不需要重新编译。
This is a simplified example to serve as a demonstration.这是一个简化的示例,用作演示。 The point is that there is a forest of dependency trees created by
#include
lines.关键是
#include
行创建了一个依赖树森林。 (The root of such a tree would be the header file of interest, and its children are the files that #include
it.) Each leaf in one of these trees represents a file that must be compiled when changes occur in the header file of interest. (这样一棵树的根是感兴趣的 header 文件,它的子文件是
#include
它的文件。)其中一棵树中的每个叶子代表一个文件,当感兴趣的 header 文件发生更改时必须编译该文件. The number of leaves in a tree grows exponentially with the depth, so removing a branch (by replacing an #include
with a forward declaration) can have a massive effect on rebuild time.树中的叶子数量随深度呈指数增长,因此删除分支(通过将
#include
替换为前向声明)会对重建时间产生巨大影响。 Or maybe a negligible effect.或者可能是微不足道的影响。 This is theory, not practice.
这是理论,不是实践。
I should note that like the question, this answer focuses on compile times, not on the other factors to consider.我应该注意到,就像这个问题一样,这个答案侧重于编译时间,而不是其他要考虑的因素。 This is not supposed to be a comprehensive guide to the pros and cons of forward declarations, just an explanation for how they could save compilation time.
这不应该是对前向声明的优缺点的全面指南,只是对它们如何节省编译时间的解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.