17

Lets say I want to use hex() function. I know it is defined in <ios> header and I also know that it is included in <iostream> header. The difference is that in <iostream> are much more functions and other stuff I don't need.

From a performance stand-point, should I care about including/defining less functions, classes etc. than more?

user229044
  • 232,980
  • 40
  • 330
  • 338
Martin Heralecký
  • 5,649
  • 3
  • 27
  • 65
  • It will effect the size of your binary file, but there won't be any performance issues i guess. – Haris Nov 13 '15 at 17:09
  • 2
    @Haris: no, that's not true, in the general case. – Paul R Nov 13 '15 at 17:12
  • @PaulR, there will be performance issues? – Haris Nov 13 '15 at 17:14
  • 5
    @Haris it will probably have very little, if any, effect on the size of the binary file. Having prototypes and declarations from the header when compiling doesn't automatically add in the related executable code (unless its used, then it's added during linking), and with dynamic linking that code would be part of the linked-to libraries rather than the executable anyway. – Dmitri Nov 13 '15 at 17:14
  • @Haris: no, I meant that in general it won't affect the size of the resulting binary, as you claim. – Paul R Nov 13 '15 at 17:15
  • An advantage of including various header files is to detect name space collisions - more of an issue in C than C++. Of course, various disadvantages as commented/answered elsewhere. – chux - Reinstate Monica Nov 13 '15 at 17:21
  • @Paul: See [`std::ios_base::Init`](http://en.cppreference.com/w/cpp/io/ios_base/Init)... – Deduplicator Nov 13 '15 at 17:51
  • @Deduplicator: OK - my bad - I think it's fair to say that it doesn't affect binary size *in the general case*, but I guess it *might* in this particular case, if nothing else were going to `#include `. – Paul R Nov 13 '15 at 17:56
  • If you want to include only the header files necessary for each of your sources, check out http://include-what-you-use.org/. It uses clang's AST to analyze your code and suggests you only include the minimum set of files necessary. – Chris Nov 13 '15 at 18:15
  • @Chris: There is one problem with such a tool though, and it's unavoidable: It depends on what is, in that specific version of toolchain+libs+project, not what's guaranteed by the contract. So one has to sanity-check anyway or accept the increased fragility. – Deduplicator Nov 13 '15 at 18:19

5 Answers5

31
  • There is no run time performance hit.
  • However, there could be excessive compile time hit if tons of unnecessary headers are included.
  • Also, when this is done, you can create unnecessary recompiles if, for instance, a header is changed but a file that doesn't use it includes it.

In small projects (with small headers included), this doesn't matter. As a project grows, it may.

Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105
Anon Mail
  • 4,660
  • 1
  • 18
  • 21
  • It's possible to add some run time overhead with static initialization of variables in a header. – Praxeolitic Nov 17 '15 at 11:16
  • You are correct. But I think that variables in headers are either done by mistake or a rare occurrence used for advanced purposes. – Anon Mail Nov 17 '15 at 17:40
31

If the standard says it is defined in header <ios> then include header <ios> because you can't guarantee it will be included in/through any other header.

Galik
  • 47,303
  • 4
  • 80
  • 117
  • This is generally wrong, because you _can_ rely on some symbols to be defined if some other header is included; consider `std::begin`. – edmz Nov 13 '15 at 19:06
  • 2
    Does anything in the question contradict or question that need? – Deduplicator Nov 13 '15 at 19:24
  • 5
    @black - you can rely on symbols being defined in the header or headers in which the standard says they are defined. Very few are required to be present in more than one header. Most implementations end up defining some symbols in more than one header because they're needed internally, but that's implementation-specific, i.e., not something you can rely on. – Pete Becker Nov 13 '15 at 21:11
5

TL;DR: In general, it is better to only include what you need. Including more can have an adverse effect on binary size and startup (should be insignificant), but mostly hurts compilation-time without precompiled headers.


Well, naturally you have to include at least those headers together guaranteed to cover all your uses.
It might sometimes happen to "work" anyway, because the standard C++ headers are all allowed to include each other as the implementer wants, and the headers are allowed to include additional symbols in the std-namespace anyway (see Why is "using namespace std" considered bad practice?).

Next, sometimes including an additional header might lead to creation of additional objects (see std::ios_base::Init), though a well-designed library minimizes such (that is the only instance in the standard library, as far as I know).

But the big issue isn't actually size and efficiency of the compiled (and optimized) binary (which should be unaffected, aside from the previous point, whose effect should be miniscule), but compilation-time while actively developing (see also How does #include <bits/stdc++.h> work in C++?).
And the latter is (severely, so much that the comittee is working on a modules-proposal, see C++ Modules - why were they removed from C++0x? Will they be back later on?) adversely affected by adding superfluous headers.

Unless, naturally, you are using precompiled-headers (see Why use Precompiled Headers (C/C++)?), in which case including more in the precompiled headers and thus everywhere instead of only where needed, as long as those headers are not modified, will actually reduce compile-times most of the time.

There is a clang-based tool for finding out the minimum headers, called include-what-you-use.
It analyzes the clang AST to decide that, which is both a strength and a weakness:
You don't need to teach it about all the symbols a header makes available, but it also doesn't know whether things just worked out that way in that revision, or whether they are contractual.
So you need to double-check its results.

Community
  • 1
  • 1
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
4

Including unnecessary headers has following downsides.

  1. Longer compile time, linker has to remove all the unused symbols.
  2. If you have added extra headers in CPP, it will only affect your code.
  3. But if you are distributing your code as a library and you have added unnecessary headers in your header files. Client code will be burdened with locating the headers that you have used.
  4. Do not trust indirect inclusion, use the header in which required function is actually defined.
  5. Also in a project as a good programming practice headers should be included in order of reducing dependency.
//local header -- most dependent on other headers
#include <project/impl.hpp>
//Third party library headers -- moderately dependent on other headers
#include <boost/optional.hpp>
//standard C++ header -- least dependent on other header
#include <string>

And things that won't be affected is run-time, linker will get rid of unused symbols during compilation.

g-217
  • 2,069
  • 18
  • 33
  • I wouldn't bother with point 5. Obviously one should include the corresponding header-file first, to make sure there are no dependency-issues, but the rest should just be sorted alphabetically as that's easy and one can reliably search for any specific one, let the compiler (and header-guards) sort it out. – Deduplicator Nov 13 '15 at 18:16
  • 2
    The linker doesn't have to "remove all the unused symbols"... the compiler doesn't add those symbols in the first place as long as the functions or objects aren't actually accessed or defined (not just declared) in the code it's compiling. – Dmitri Nov 13 '15 at 18:24
  • +1 "Do not trust indirect inclusion." Stephan T. Lavavej, ("STL") is the maintainer of Visual Studio's STL implementation. He explicitly says this because there are cases where types are moved around in headers and if you say, `#include iostream` knowing it also includes `istream` for `std::cin` and `iostream` stops including `istream` your code with break. Always include headers for the types you need, don't rely on indirection. – Casey Nov 13 '15 at 19:40
  • @Dmitri the linker is allowed to remove symbols that are not referenced anywhere else in the object code as long as they are not exported. –  Nov 13 '15 at 21:00
  • @Casey you can trust standard library.. but you may not want to do that for third party libraries... like your logger library has boost::format and you chose to ignore "boost/format.hpp", but moment your logger changes it's implementation, your code will blow up. – g-217 Nov 13 '15 at 21:19
  • @Snowman I'm not saying the linker can't remove unused symbols... I'm saying that just including declarations (like in a header file) doesn't necessarily *add* unused symbols for it to remove. A function that's defined (not just declared) but never called would be an example of something the linker might actually remove, though. – Dmitri Nov 13 '15 at 22:21
  • @Dmitri fair enough, I was focusing on the first part of your statement. Reading it again, I think we're both right. –  Nov 14 '15 at 04:10
1

Including unneeded header files has some value.

  1. It does take less coding effort to include a cut and paste of the usually needed includes. Of course, later coding is now encumbered with not knowing what was truly needed.

  2. Especially in C, with its limited name space control, including unneeded headers promptly detects collisions. Say code defined a global non-static variable or function that happened to match the standard, like erfc() to do some text processing. By including <math.h>, the collision is detected with double erfc(double x), even though this .c file does no FP math yet other .c files do.

    #include <math.h>
    char *erfc(char *a, char *b);
    

OTOH, had this .c file not included <math.h>, at link time, the collision would be detected. The impact of this delayed notice could be great if the code base for years did not need FP math and now does, only to detect char *erfc(char *a, char *b) used in many places.

IMO: Make a reasonable effort to not include unneeded header files, but do not worry about including a few extra, especially if they are common ones. If an automated method exist, use it to control header file inclusion.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256