W pierwszych wersjach C++ członkowie klasy byli inicjalizowani wewnątrz konstruktora przez przypisanie. Później pojawiła się możliwość inicjalizacji członków klasy przed wejściem do ciała konstruktora przy pomocy listy inicjalizacyjnej, co jest krytyczne dla członków stałych, odniesień oraz wydajności.
Niektórzy członkowie klasy (np. pola const lub odniesienia) nie mogą być inicjalizowani przez przypisanie wewnątrz ciała konstruktora — muszą być określone w momencie tworzenia. Dodatkowo, jeśli użyć przypisania, najpierw zostanie wywołany domyślny konstruktor, a potem przypisanie (dwie operacje), co może być kosztowne dla złożonych obiektów:
class Example { const int x; std::string str; public: Example(int val, const std::string& s) : x(val), str(s) {} };
Użyj listy inicjalizacyjnej, aby od razu zainicjalizować członków klasy. Jest to szczególnie ważne dla const, odniesień, członów klas bez konstruktora domyślnego, a także dla wydajności przy pracy z klasami STL i dużymi strukturami.
Przykład kodu:
class Point { const int x; int& y; public: Point(int val, int& ref) : x(val), y(ref) {} };
Kluczowe cechy:
Czy można zmienić kolejność inicjalizacji członków klasy przez kolejność w liście inicjalizacyjnej konstruktora?
Nie! Członkowie są zawsze inicjalizowani w kolejności ich deklaracji w klasie, a nie według kolejności w liście inicjalizacyjnej. Ignorowanie tej zasady prowadzi do błędów kolejności inicjalizacji.
Co się stanie, jeśli odniesienie nie zostanie zainicjalizowane w liście inicjalizacyjnej, a tylko w ciele konstruktora?
Błąd kompilacji! Odniesienie, podobnie jak pola const, można zainicjalizować tylko w liście inicjalizacyjnej — muszą one otrzymać wartość przed wejściem do ciała konstruktora.
Czy po zainicjalizowaniu członu const w liście inicjalizacyjnej można zmienić go w ciele konstruktora?
Nie, człon stały nie może być zmieniany po inicjalizacji — próba zmiany takiego pola prowadzi do błędu kompilacji.
W konstruktorze członek klasy jest inicjalizowany wewnątrz ciała konstruktora. Dla złożonych obiektów wydawane są zasoby na wywołanie domyślnego konstruktora, potem na przypisanie, a następnie na zniszczenie obiektu tymczasowego.
Zalety:
Wady:
Wszystkie człony są od razu inicjalizowane w liście inicjalizacyjnej, nie ma zbędnych operacji ani problemów z niemutowalnymi polami.
Zalety:
Wady: