0

Assume we have two files

a.cc

#include <iostream>

int timesTwo(int in);

int main(){
 std::cout << timesTwo(5) << std::endl;
 return 0;
}

b.cc

int timesTwo(int in){
 return in*2;
}

is it better to use the linker and include b.cc in a.cc by #include "b.cc" or is it better to leave it as is and compile them like g++ a.cc b.cc? What are the circumstance where one is preferred over the other?

6

The main point of header files is to give access to the definitions without having to rebuild unchanged code every time you compile. That's certainly what happens when you include something like iostream.h as it's not like you've got to compile the library from scratch every time you use it.

For a three line function there's probably not too much of a hit, but it's a bad habit to get into and you will pay a penalty for doing things that way when you get onto larger projects.

So, definitely go with g++ a.cc b.cc for now, and take a look at build automation tools before you add more files too.

2

Tiny examples don't necessarily capture all the relevant issues.

In the C and C++ universes, compiling is time consuming and linking is fast. In a large project your code will be broken up into dozens if not hundreds of files. It may take half-an-hour to half-a-day for it all to compile from scratch. That means you really want to avoid re-compiling code that doesn't actually need to be re-compiled.

If you put that code in a header file it will get recompiled every time a file that includes that header gets re-compiled, even if the header itself hasn't changed. Move that code into its own cc file and you only need to recompile it when the code actually changes.

  • 1
    linking is fast Until you turn on Link Time Optimization. ;) But the price of that is the same in both scenarios. – D Drmmr Jan 30 at 1:28
  • 2
    In the C and C++ universes, compiling is time consuming and linking is fast. - only when your build system provides an incremental linker. And even then, static linkage can be considerably slower than dynamic linkage, so for large scale C++ projects is often beneficial to use dynamically linked libs. – Doc Brown Jan 30 at 9:53
  • Perhaps a better way to put it would be that compiling plus linking is generally more time-consuming than linking alone. – Christian Hackl Feb 5 at 8:33
1

As a general rule, you want to put code into source files when you can, and put it into headers when you have no other (reasonable) choice.

For the example you've given, a source file is clearly preferred.

But, if you decided to turn that into a function template to multiply an object of some arbitrary type by two:

template <class T>
T timesTwo(T in) { 
    return in * 2;
}

...then (at least with most compilers) you'd have little choice but to put it into a header. If you tried to put it into a source file and just link it, with many (most?) compilers, you'd get an "undefined external" error.

1

When you compile a source file (.cc), the compiler chugs through the [thousands and thousands of lines of] code that you've written and creates an object file (.o). If you include other source (.cc) files, then the compiler will chug through all of those as well, taking [a lot] longer to do so.

You want to be working in such a way that you compile only the code you're working on - why wait several hours for a compile to finish when the bit you're working on only takes a few seconds?

Obligatory XKCD Reference: Compiling

So; how do you "isolate" the bit you're working on to avoid all that unnecessary recompilation time?

Answer: You work in a "Modular" way, including only the definitions for any other bits of code you [re-]use. That way, the compiler sees only your code, plus those definitions; it never gets a look at the code (implementation) for the other bits.

Note: The Compiler doesn't care that it doesn't know about the implementation of those included functions. It only needs to know the "shape" of each function so that it can check your code against it. Threading all these prototypes, calls and implementations together is the Linker's job!

All that "definition" information is what goes in the "Header" files.

For example:

b.cc

int timesTwo(int in){
 return in*2;
}

b.h

int timesTwo(int); /* This is a "function prototype" */ 

a.cc

#include <iostream>
#include "b.h"

int main(){
 std::cout << timesTwo(5) << std::endl;
 return 0;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.