Kiedyś spotkałem się z opinią, że jeśli #include <Foo>
wpiszemy w pliku *.cpp, a w pliku *.h zrobimy forward declaration class Foo;
zamiast dać tylko #include <Foo>
w pliku *.h to "będzie szybciej".
I tu się pojawiają się moje pytania, czy to prawda, co będzie szybciej i dlaczego?
Co miałoby być szybsze: kompilacja czy wynikowy program?
Plus: o jakim kompilatorze mówimy?
No właśnie nie wiem, co miałoby być szybsze, wydaje mi się, że na wynikowy program to chyba nie ma wpływu, raczej na czas kompilacji...
Kompilator GCC.
W większych programach może mieć to znaczący wpływ na czas kompilacji, m.in. dlatego powstał idiom PIMPL. Dodatkowo, modyfikacja definicji klasy wymaga rekompilacji wszystkich TU, które ją widzą, więc jeśli z niej gdzieś nie korzystasz (t.j. nie potrzebujesz pełnej definicji), to warto jej nie inkludować. Dotyczy to w szczególności typów, które mogą ulec zmianom. Np. w przypadku std::string
jest to bezsens, ale jakieś FooObject
w Twoim projekcie już potencjalnie tak.
Rożnica jest ogromna.
Tu masz mój post opisujący zasady forward declaration: https://4programmers.net/Forum/C_i_C++/137960-C++_Unikanie_include_w_plikach_naglowkowych?p=513176#id513176
Gdzie widziałem artykuł google, który to analizował dla swoich projektów. Naprawienie tego przyspieszyło im proces budowania o 60% (tak mało, bo nie mieli z tym dużo bałaganu).
Zresztą jest więcej trików by unikać kaskady przebudowywania TU przy zmianie jednego nagłówka. Przykładowo popatrz na to:
Oprócz znanych metod (deklaracje zapowiadające, faktoring, ukrywanie implementacji, klasy protokolarne...), nawet pomaga dodatkowa kontrola włączenia nagłówka. Tu trochę przesadzę ale w celu uświadomienia problemu...
Zakładając że masz gęste połączenia N<->N (czyli każdy z każdym) wielu nagłówków, jeśli kompilator będzie otwierał każdy z nagłówków prawidłowo opatrzony makrami-strażnikami, będzie parsował cały plik aż do #endif bo przecież po nim może być coś co wymaga pracy kompilatora. Nawet "brzydkie"...
// sample.hpp
#ifndef _INCLUDED_SAMPLE_HPP
#define _INCLUDED_SAMPLE_HPP
#ifndef _INCLUDED_SAMPLE1_HPP
#include <sample1.hpp>
#endif
#ifndef _INCLUDED_SAMPLE2_HPP
#include <sample2.hpp>
#endif
// itd...
#endif // _INCLUDED_SAMPLE_HPP
... pomaga bo kompilator nie będzie otwierał nowego nagłówka aby w większości przypadków przekonać się że "nie ma nic do roboty". Oczywiście to nie powinno być jedyne rozwiązanie z którego się korzysta.
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.