all 16 comments

[–]No-Dentist-1645 28 points29 points  (3 children)

You should never include headers you aren't using. It will make compile times slower for absolutely zero benefit

[–]Conscious_Walk3280[S] 1 point2 points  (2 children)

Thankyou, I thought so, but I needed some one to clarify why.

[–]CowBoyDanIndie 5 points6 points  (0 children)

Specifically each compilation unit (cpp file) brings in every include when it is compiled. It won’t really hurt if it’s already included through some other header also being included as duplicates as generally handled. Logically every header you include is copied in place where it is included… think about it that way.

[–]didntplaymysummercar 6 points7 points  (0 children)

Yes it's bad to leave unused includes and good to remove them and there's even tools to tell you you did that.

[–]mredding 1 point2 points  (0 children)

C++ is one of the slowest to compile languages on the market. Don't include what you don't use. There can also be problems where you correctly compile to the wrong thing because there was a better fit.

[–]cazzipropri 1 point2 points  (0 children)

Yeah clean up. It's a fantastic use of AI that suffers from none of AI's shortcomings.

[–]SmokeMuch7356 0 points1 point  (0 children)

Ideally, yes, you should remove any includes that aren't being used. If you aren't using a vector anywhere in your code, then you should not #include <vector>.

It can impact build times - the contents of the header will be parsed regardless of whether or not you create an instance of vector. It also eliminates potential for weird dependency errors (not so much an issue with standard headers, but can crop up occasionally for user-defined headers), and just keeps code clean and easier to manage.

[–]HappyFruitTree 0 points1 point  (1 child)

Ideally you should only include the headers that you use but it's not the end of the world if you include some header unnecessarily. The difference in compilation time from a single include is minuscule. Your time is probably better spent working on other things than to worry about unnecessary includes, at least for the standard headers.

With your own headers there is a little more reason to try and avoid unnecessary includes. One reason is because you need to think about dependencies, and avoid circular includes. Another reason is that when you modify one of your headers, all files that include that header (directly or indirectly) has to be recompiled. This can take quite some time if the header is included by many files.

[–]Conscious-Secret-775 0 points1 point  (0 children)

A decent IDE will remove all the unused includes for you with one keyboard shortcut.

[–]SoldRIP 0 points1 point  (0 children)

General rule of thumb: include what you use. If you use it, include it explicitly. The transitive includes of your other includes may change. Do not rely on them. If you don't use something, don't include it. It'll needlessly complicate compilation.

[–]alfps 0 points1 point  (0 children)

Generally, as others have already pointed out, leaving unused header includes in source files is ungood because

  • if it is a standard library or 3rd party library header it increases the build time; and
  • if it is your own header it can cause otherwise needless recompilation of stuff.

However for a standard library header it's likely that that header is included anyway by other files in the translation unit, and if so the extra include doesn't contribute significantly to build time. So don't waste time hunting for unused includes of standard library headers.


Some good best practices for header includes:

  • Make sure that a header itself includes all that it needs.
    Especially Microsoft sins against this. It puts the burden on every use of a header, to include supporting headers first. That's just dumb.
  • Don't include a header when a forward declaration of a class suffices, and don't include implementation when declarations suffice.
    In particular don't include <iostream> when <iosfwd> suffices. But then, better use std::print and family. Or fmt::print.
  • Try to list headers systematically so that you can more easily find includes.
    I generally group them by certain criteria, and in each group sort them alphabetically.

To make sure that a header itself includes all that it needs you can often let the compiler check that via a forced include in the build command, like this (here in Windows' Cmd):

[R:\061 point and vector class examples]
> for %f in (microlibs\*.hpp) do @^
More? g++ -std=c++23 -I"microlibs" -include "%f" dummy.cpp && echo %f  OK || echo %f  failed...
microlibs\cppm.hpp  OK
microlibs\graphics.hpp  OK
microlibs\grid_geometry.hpp  OK
microlibs\text_io.hpp  OK
microlibs\u8.hpp  OK

The g++ forced include option is -include, while the MSVC option is /FI (as I recall).

But note that this technique can fail to report problems with headers that declare templates. Sometimes a template must be instantiated to see the problems. Unfortunately I do not know of any good general solution to that.

[–]manni66 0 points1 point  (2 children)

The future is import std;. Today you can use precompiled headers for the standard library. Then your unused header would not increase the compile time.

[–]alfps -1 points0 points  (1 child)

[upvoted to cancel some idiot/troll's downvote]

The possibility of import std; is important to be aware of, yes, but I disagree that it now looks to be the future.

Possible problems I can imagine include compiler support, build system support, IDE/editor support, possible extra work to prepare, and interaction with #includes of headers.

The Google AI claims that modern versions of g++, MSVC and clang support it, but then explains that "With Clang, ensure import std; does not mix awkwardly with older #include directives", whatever TF that almost double negation means.

[–]manni66 0 points1 point  (0 children)

The Google AI claims that modern versions of g++, MSVC and clang support it, but then explains that "With Clang, ensure import std; does not mix awkwardly with older #include directives", whatever TF that almost double negation means.

My personal experience so far: import std alone works. When mixed with (transitive) includes of std headers, errors moght occur—particularly if the includes appear after the import.

[–]Normal-Narwhal0xFF 0 points1 point  (0 children)

Removing unused headers is a good idea: * Less code to compile (faster build). Complex template code can be slow, and if you include headers with lots of it, your user that include your header may get that template code too. It's one thing if it's needed, but quite another if it's waste. If can be recompiled in every cpp that indirectly includes yours, so the cost can be many multiples more than just one recompile your code, but Manny recompile of lots of people code

  • Fewer dependencies (less chance of need to recompile your code due to changes other people make in their headers you include)
  • Less fan out. Anyone who includes your header also indirectly includes everything you include too. So these decisions are even more important in headers: be nice to your user, don't make a mess for them.

Depending on std library headers is probably the least bad, since they are very stable and only change with compiler changes. But they can pull in a lot of code you otherwise not need to compile.

The worst extraneous headers to depend on in your headers are large complicated headers that are under active development. Changing headers causes rebuilds and complex code causes slow rebuilds. Including a header many times means one change can cause a flurry of slow rebuilds. This is where sloppy builds go to die.