Speed up compile times with forward declarations

I am a self taught programmer and developed many bad habits as I was learning. I never read any books on proper programming structure, and really regret it now. I made so many easily avoidable mistakes.

This post describes a simple concept but when I initially figured it out it was a bit of a “eureka” moment for me.

In a large project, compile times can really get bogged down, especially if you are using things like templates. A bad design will have a horrible web of classes, all files referring to each other in some way. The problem is that when you touch one header file, it has a domino effect and triggers a rebuild of the majority of source files.

Here are a few files to explain the issue:

————- A.h ————-

#pragma once
struct SimpleStruct { int dummy_value; };

————- B.h ————-

#include "A.h"
void doSomethingToASimpleStruct(SimpleStruct* TheStruct);

————- B.cpp ————-

#include "B.h"
void doSomethingToASimpleStruct(SimpleStruct* TheStruct) {
   TheStruct->dummy_value = 10;
}

————- C.h ————-

#include "B.h"
void theCallingFunction();

————- C.cpp ————-

#include "C.h"
void theCallingFunction() {
   SimpleStruct* a_simple_struct = new SimpleStruct();
   doSomethingToASimpleStruct(a_simple_struct);
   delete a_simple_struct;
}

With the above code, what happens if we modify our struct? Well, it is included in B.h, which is included by both B.cpp and C.cpp, causing a full rebuild of both cpp files. However, we are not actually using the structure of SimpleStruct in B.h. We just use a pointer to one, without needing to know what it is. If only there was some way of saying to the compiler, “we’re using a pointer to something here, but we want to declare it later, so we’re just letting you know it will exist.”

That’s where forward declarations come in.
With a slight modification:

————- B.h ————-

struct SimpleStruct; // FORWARD DECLARATION
void doSomethingToASimpleStruct(SimpleStruct* TheStruct);

————- B.cpp ————-

#include "B.h"
#include "A.h"
void doSomethingToASimpleStruct(SimpleStruct* TheStruct) {
   TheStruct->dummy_value = 10;
}

We have moved the include of A.h from B.h to B.cpp. B.h just knows OF the SimpleStruct, so that it can legally use a pointer to it, but it doesn’t need to know what’s in it. It will all get linked up later no problem. Now, when SimpleStruct changes, B.cpp does get recompiled, but C.cpp doesn’t. This is just a very simple contrived example, but if you can apply this to larger projects, you might see a drastic increase in compile/rebuild times.

I know this kind of thing is obvious to people who learned programming a proper way, but like I say, it was a revelation for me. Hopefully, this post might make a few beginner programmers nod and say, “ah, I get it now,” in the same way as I did when I finally understood the point of forward declarations.

Published by

samuraigoblin

Just a programmer who loves sushi.

Leave a Reply

Your email address will not be published. Required fields are marked *