4

同じヘッダーファイルを複数回インクルードすると、コンパイル時間が長くなりますか?

たとえば、プロジェクト内のすべてのファイルがとを使用する<iostream> <string> <vector>とし<algorithm>ます。また、ソースコードに多くのファイルを含めると、コンパイル時間が長くなりますか?

ガードヘッダーは二重定義を回避するという重要な目的を果たしていると常に思っていましたが、副産物として二重コードも排除されています。

実際、私が知っている誰かが、そのような複数の包含を削除するためのいくつかのアイデアを提案しました。ただし、これらはC++の優れた設計手法に完全に反していると思います。しかし、彼が変更を提案する理由は何でしょうか?

4

8 に答える 8

13

これらの答えのほとんどは間違っています...最近のコンパイラではヘッダーが通常の「インクルードガード」イディオムを使用していると仮定すると、同じファイルを複数回インクルードするオーバーヘッドはありません。

たとえば、GCCプリプロセッサには、インクルードガードイディオムを認識するための特別なコードがあります。#include2番目以降のディレクティブのヘッダーファイルも開きません(読んでもかまいません) 。

他のコンパイラについてはよくわかりませんが、ほとんどのコンパイラが同じ最適化を実装していなかったとしたら、非常に驚​​きます。

于 2011-08-19T15:53:51.377 に答える
1

プリコンパイル済みヘッダー以外の別の手法は、コンパイラファイアウォールのイディオムです。ここで説明します。

http://www.gotw.ca/publications/mill04.htm

http://www.gotw.ca/publications/mill05.htm

于 2011-08-19T15:47:10.090 に答える
1

ソースファイルで発生するたび#include <something.h>に、「something.h」をインクルードパスに沿って見つけて読み取る必要があります。しかし、#ifndef _SOMETHING_H_チェックがあるので、そのようなsomething.hのコンテンツはコンパイルされません。したがって、いくらかのオーバーヘッドがありますが、それは本当に小さいです。

于 2011-08-19T15:48:17.523 に答える
1

コンパイル時間が問題になる場合、人々は、元々は大規模ソフトウェア設計で推奨されていた、Praetorianが推奨する最適化を使用していました。ただし、最新のコンパイラのほとんどは、この場合に自動的に最適化されます。たとえば、gccのヘルプを参照してください

于 2011-08-19T15:55:50.650 に答える
0

最善の方法は、プリコンパイル済みヘッダーを使用することです。使用しているコンパイラはわかりませんが、ほとんどのコンパイラにこの機能があります。これを実現する方法については、コンパイラのマニュアルを参照することをお勧めします。

基本的に、すべてのヘッダーファイルを収集し、それをオブジェクトファイルにコンパイルして、リンカで使用できるようにします。これにより、コンパイルが非常に高速化されます。

マイナーな欠点:

すべてのコンパイルユニット(.cpp)に含まれる1つの「uberheader」が必要です。

そのuberheaderには、ライブラリからの静的ヘッダーのみを含め、独自のヘッダーは含めないでください。そうすれば、コンパイラはそれを頻繁に再コンパイルする必要はありません。

それは特に役立ちます。boostやglm、eigenなどのヘッダーのみのライブラリを使用する場合。

HTH

于 2011-08-19T15:42:17.197 に答える
0

はい、同じヘッダーを複数回含めるということは、プリプロセッサガードが起動して複数の定義を防ぐ前に、ファイルを開く必要があることを意味します。Mozillaのソースコードは、これを防ぐために次のトリックを使用しています。

Foo.h

#ifndef FOO_H
#define FOO_H

// whatever

#endif  /* FOO_H */

foo.hを含める必要があるすべてのファイル

#ifndef FOO_H
#include "foo.h"
#endif

これにより、foo.hを複数回開く必要がなくなります。もちろん、これは、プリプロセッサガードの特定の命名規則に従うすべての人に依存します。

プリプロセッサガードには一般的な命名規則がないため、標準ヘッダーではこれを行うことはできません。

編集:
あなたの質問をもう一度読んだ後、あなたは同じヘッダーが異なるソースファイルに含まれていることについて質問していると思います。私が上で話したことがそれを助けません。各ヘッダーファイルを開いて、すべての翻訳ユニットに少なくとも1回インクルードする必要があります。これを防ぐために私が知っている唯一の方法は、@ scorcher24が彼の回答で述べたように、プリコンパイル済みヘッダーを使用することです。ただし、コンパイル時間が絶対に禁止されていない限り、コンパイラ間でプリコンパイル済みヘッダーを生成する標準的な方法がないため、このソリューションには近づきません。

于 2011-08-19T15:44:00.907 に答える
0

一部のコンパイラ、特にMicrosoftのコンパイラには#pragma once、インクルードファイルがすでにインクルードされた後に自動的にスキップするために使用できるディレクティブがあります。これにより、パフォーマンスの低下がなくなります。

http://en.wikipedia.org/wiki/Pragma_once

于 2011-08-19T15:54:03.273 に答える
0

問題になる可能性があります。他の人が言っているように、ほとんどの最新のコンパイラはケースをインテリジェントに処理し、縮退したケースでのみファイルを再度開きます。ただし、ほとんどがすべてではありません。主要な例外の1つは、多くの人がサポートしなければならないMicrosoftです。最も確実な解決策(これが実際に環境で問題になる場合)は、Lakos規則を使用して #include、ヘッダーと同様にインクルードガードを配置することです。これは、もちろん、ガード名を生成するための標準的な規則を意味します。(外部インクルードの場合は、ローカルの規則を尊重する独自のヘッダーでラップします。)または、ガードと。の両方を使用できます#pragma once。ガードは常に機能し、ほとんどのコンパイラは余分なオープンを回避し、#pragma once通常、Microsoftでの余分なオープンを回避します。(#pragma once複雑なネットワーク環境では確実に実装することはできませんが、すべてのファイルがローカルドライブにある限り、非常に信頼性があります。)

于 2011-08-19T16:22:10.617 に答える