Achtergrond:
In klassiek C++ werden klasseleden alleen geïnitieerd in de initialisatielijst van de constructor. Met C++11 is het mogelijk om standaardwaarden direct in de declaratie binnen de klasse op te geven (member initializers) om de leesbaarheid en veiligheid van de code te verbeteren.
Probleem:
Er zijn verschillende manieren om een waarde aan een klasse lid toe te wijzen: direct in de declaratie (in-class), via de initialisatielijst van de constructor en al in het lichaam van de constructor. Verschillende methoden hebben invloed op de prestaties en semantiek; een misverstand kan leiden tot overbodige kopieën of default destructors, evenals fouten met constanten en referenties.
Oplossing:
class MyClass { int x = 42; };
class MyClass { const int y; MyClass(int val) : y(val) {} // anders — compilatiefout };
class MyClass { std::string s; MyClass() { s = "hello"; } // Eerst default, dan toewijzing };
Belangrijke kenmerken:
Wat is de volgorde van initialisatie van leden: in de volgorde waarin ze in de klasse zijn gedeclareerd, of in de volgorde van de initialisatielijst?
De volgorde van initialisatie is altijd die waarin de leden in de klasse zijn gedeclareerd, en niet in de volgorde van de initialisatielijst. Het overtreden van de volgorde is gevaarlijk voor afhankelijke leden.
class A { int x = 1; int y = 2; A() : y(10), x(20) {} }; // x wordt eerder geïnitialiseerd dan y, ondanks de volgorde in de lijst
Kan een lid-constante binnen het lichaam van de constructor worden geïnitialiseerd als deze niet in de initialisatielijst is geïnitialiseerd?
Nee. Constanten worden alleen geïnitialiseerd in de initialisatielijst. Toewijzing binnen het lichaam van de constructor — compilatiefout.
Wat gebeurt er als een standaardwaarde wordt gegeven voor een lid direct in de klasse via een in-class initializer en deze wordt overschreven in de initialisatielijst van de constructor?
De waarde uit de initialisatielijst van de constructor zal worden gebruikt. De standaardwaarde wordt alleen gebruikt als de lijst niets opgeeft.
class C { int x = 10; C() : x(20) {} // x zal gelijk zijn aan 20 };
De klasse werkt met een bestand. Het bestand is gedeclareerd als std::ofstream en wordt geïnitialiseerd in het lichaam van de constructor. Gevaar: bij de default constructor kan een ongeldig std::ofstream worden gemaakt, wat leidt tot fouten bij het werken met het bestand.
Voordelen:
Nadelen:
Het bestand wordt geïnitialiseerd in de initialisatielijst, waardoor foutief gebruik van het bestand in een ongeldig state wordt geblokkeerd, terwijl leden met standaardgegevens gebruik maken van in-class initializers.
Voordelen:
Nadelen: