[Interest] Compile Speed Question regarding MOC

Till Oliver Knoll till.oliver.knoll at gmail.com
Wed Feb 19 09:21:01 CET 2014


Am 19.02.2014 um 05:10 schrieb Constantin Makshin <cmakshin at gmail.com>:

> Look at the problem from the other side:
> 1) separate "moc_*.cpp" has to be compiled only during full [re]builds
> or when the corresponding class' header file is changed;
> 2) when "moc_*.cpp" is #include-d into the implementation .cpp file,
> they are both compiled at every change.

With regards to 1): A ful rebuild takes the time it takes, no matter what. You can speed that up things as others have suggested (#include the mocced files, AUTOMOC), but that's that.

As full rebuilds are (usually) done "offline" on some build/integration/test server, time does not really matter, unless the build is not ready the next morning ;)


IMHO what is more important is to speed-up incremental builds 2), as those times are most annoying for every developer.

So here are my general tips to avoid /dependencies/:

In headers, #include only what is really necessary!

- Use forward declarations as much as possible

E.g. when you pass along a QString as parameter, do it "by reference" instead of "by value", if possible (even though we know the later is cheap due to "copy on write" semantics of most Qt container classes).

class QString; // forward declaration

class Foo {
public:
  Foo(const QString &theString);
  ...
}

Do that especially with your own classes (because you are unlikely to change the QString header anyway ;))


- Use the "private *d" idiom

 (there is a name for it which I don't recall at the moment)

/That/ saves you a lot of dependencies!

E.g.

class BarPrivate: // again, forward declare, avoid dependency!

class Bar {
public:
  ...
private:
  BarPrivate *d;
}

Then you declare and instantiate/destroy (new/delete) that member class in the *.cpp file (only). Now you can start messing around with BarPrivate and add/remove members as you wish - the consumers of your Bar class will never notice and won't need to recompile!

Off course there are some downsides, too: if you have many many instances of Bar, you end up with many many (small) dynamic allocations, possibly leading to "memory fragmentation".

Also if you want to inherit from Bar and at the same time want to have direct access to its (now protected) members, there is some extra effort to do with that "d pointer" pattern - see Qt code and its use of helper macros ;)


- Does it /need/ to be an "is-a" relation?

Or wouldn't a "has-a" relation not fit the problem better anyway?

This is one of the "classic" design questions ;)

In my general experience "people just inherit too much" (and hence introduce dependencies on the base class, instead of hiding that dependency with a "has-a" relationship, e.g. implemented with the d-pointer pattern above).



When you follow those advises and really need to change a header in some lower library class then the impact will be kept to a minimum :)


Cheers,
  Oliver


More information about the Interest mailing list