Initialiseringsliste bruges til at initialisere datamedlemmerne i en klasse. Listen over medlemmer, der skal initialiseres, er angivet med konstruktør som en kommasepareret liste efterfulgt af et kolon. Følgende er et eksempel, der bruger initialiseringslisten til at initialisere x og y i punktklassen.
Eksempel
C++
#include> using> namespace> std;> class> Point {> private>:> >int> x;> >int> y;> public>:> >Point(>int> i = 0,>int> j = 0): x(i), y(j) {}> >/* The above use of Initializer list is optional as the> >constructor can also be written as:> >Point(int i = 0, int j = 0) {> >x = i;> >y = j;> >}> >*/> >int> getX()>const> {>return> x; }> >int> getY()>const> {>return> y; }> };> int> main()> {> >Point t1(10, 15);> >cout <<>'x = '> << t1.getX() <<>', '>;> >cout <<>'y = '> << t1.getY();> >return> 0;> }> |
>
>Produktion
x = 10, y = 15>
Ovenstående kode er blot et eksempel på syntaks for Initializer-listen. I ovenstående kode kan x og y også let initialiseres inde i konstruktøren. Men der er situationer, hvor initialisering af datamedlemmer inde i constructor ikke virker, og Initializer List skal bruges. Følgende er sådanne tilfælde:
1. Til initialisering af ikke-statiske konstdatamedlemmer
const data medlemmer skal initialiseres ved hjælp af Initializer List. I det følgende eksempel er t et const-datamedlem af Test-klassen og initialiseres ved hjælp af Initializer List. Grunden til at initialisere const data-medlemmet i initialiseringslisten er, fordi der ikke er allokeret nogen hukommelse separat til const-data-medlemmet, det foldes i symboltabellen, hvorfor vi skal initialisere det i initialiseringslisten.
Det er også en parametriseret konstruktør, og vi behøver ikke at ringe til opgaveoperatøren, hvilket betyder, at vi undgår en ekstra operation.
Eksempel
C++
// C++ progmram to demonstrate the use of> // initializer list to initialize the const> // data member> #include> using> namespace> std;> class> Test {> >const> int> t;> public>:> >//Initializer list must be used> >Test(>int> t):t(t) {}> >int> getT() {>return> t; }> };> int> main() {> >Test t1(10);> >cout< return 0; }> |
>
>Produktion
10>
2. Til initialisering af referencemedlemmer
Referencemedlemmer skal initialiseres ved hjælp af initialiseringslisten. I det følgende eksempel er t et referencemedlem af testklassen og initialiseres ved hjælp af Initializer List.
Eksempel
C++
netværkstopologi
// Initialization of reference data members> #include> using> namespace> std;> class> Test {> >int> &t;> public>:> >Test(>int> &t):t(t) {}>//Initializer list must be used> >int> getT() {>return> t; }> };> int> main() {> >int> x = 20;> >Test t1(x);> >cout< x = 30; cout< return 0; }> |
>
>Produktion
20 30>
3. Til initialisering af medlemsobjekter, der ikke har en standardkonstruktør
I det følgende eksempel er et objekt a i klasse A et datamedlem af klasse B, og A har ikke en standardkonstruktør. Initialiseringsliste skal bruges til at initialisere en.
Eksempel
C++
// C++ progmam to initialize a member object without default> // constructor> #include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int>);> };> A::A(>int> arg)> {> >i = arg;> >cout <<>'A's Constructor called: Value of i: '> << i> ><< endl;> }> // Class B contains object of A> class> B {> >A a;> public>:> >B(>int>);> };> B::B(>int> x) : a(x)> {>// Initializer list must be used> >cout <<>'B's Constructor called'>;> }> int> main()> {> >B obj(10);> >return> 0;> }> |
>
>Produktion
A's Constructor called: Value of i: 10 B's Constructor called>
Hvis klasse A havde både standard- og parametriserede konstruktører, så er Initializer List ikke et must, hvis vi ønsker at initialisere en ved hjælp af standardkonstruktøren, men det er et must for at initialisere en ved hjælp af den parametriserede konstruktør.
4. Til initialisering af basisklassemedlemmer
Ligesom punkt 3 kan den parametriserede konstruktør af basisklassen kun kaldes ved hjælp af Initializer List.
Eksempel
C++
#include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int> );> };> A::A(>int> arg) {> >i = arg;> >cout <<>'A's Constructor called: Value of i: '> << i << endl;> }> // Class B is derived from A> class> B: A {> public>:> >B(>int> );> };> B::B(>int> x):A(x) {>//Initializer list must be used> >cout <<>'B's Constructor called'>;> }> int> main() {> >B obj(10);> >return> 0;> }> |
>
>Produktion
A's Constructor called: Value of i: 10 B's Constructor called>
5. Når konstruktørens parameternavn er det samme som datamedlem
Hvis konstruktørens parameternavn er det samme som datamedlemsnavnet, skal datamedlemmet initialiseres enten vha denne pointer eller Initialiseringsliste. I det følgende eksempel er både medlemsnavnet og parameternavnet for A() i.
Eksempel
C++
char til int
#include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int>);> >int> getI()>const> {>return> i; }> };> A::A(>int> i) : i(i)> {> }>// Either Initializer list or this pointer must be used> /* The above constructor can also be written as> A::A(int i) {> >this->i = i;> }> */> int> main()> {> >A a(10);> >cout << a.getI();> >return> 0;> }> |
>
>Produktion
10>
6. Af præstationsmæssige årsager
Det er bedre at initialisere alle klassevariabler i Initialiseringslisten i stedet for at tildele værdier inde i kroppen. Overvej følgende eksempel:
Eksempel
C++
// Without Initializer List> class> MyClass {> >Type variable;> public>:> >MyClass(Type a) {>// Assume that Type is an already> >// declared class and it has appropriate> >// constructors and operators> >variable = a;> >}> };> |
>
>
Her følger compiler følgende trin for at oprette et objekt af typen MyClass
1. Types konstruktør kaldes først for en.
2. Standard konstruktionsvariabel
3. Tildelingsoperatoren af Type kaldes inde i brødteksten af MyClass()-konstruktøren for at tildele
variable = a;>
4. Og så til sidst kaldes destructor af Type til en, da den går uden for scope.
Overvej nu den samme kode med MyClass()-konstruktøren med Initializer List
C++
// With Initializer List> class> MyClass {> >Type variable;> public>:> >MyClass(Type a):variable(a) {>// Assume that Type is an already> >// declared class and it has appropriate> >// constructors and operators> >}> };> |
>
>
Med Initializer List, følges følgende trin af compiler:
1. Types konstruktør kaldes først for en.
2. Parametriseret konstruktør af Type-klassen kaldes til at initialisere: variabel(a). Argumenterne i initialiseringslisten bruges til at kopiere konstruktionsvariable direkte.
3. Destruktoren af Type kaldes for a, da den går uden for anvendelsesområdet.
Som vi kan se fra dette eksempel, hvis vi bruger tildeling inde i konstruktørens krop, er der tre funktionskald: konstruktør + destruktor + et tillægstildelingsoperatørkald. Og hvis vi bruger Initializer List er der kun to funktionskald: copy constructor + destructor call. Se dette indlæg for et kørende eksempel på dette punkt.
Denne tildelingsstraf vil være meget mere i rigtige applikationer, hvor der vil være mange sådanne variabler. Tak til ptr for at tilføje dette punkt.
Parameter vs ensartet initialisering i C++
Det er bedre at bruge en initialiseringsliste med ensartet initialisering {} frem for parameterinitialisering () for at undgå problemet med indsnævre konverteringer og uventet adfærd. Det giver strengere typekontrol under initialisering og forhindrer potentielle indsnævre konverteringer
Kode ved hjælp af parameterinitialisering ()
C++
#include> class> Base {> >char> x;> public>:> >Base(>char> a)> >: x{ a }> >{> >}> >void> print() { std::cout <<>static_cast><>int>>(x); }> };> int> main()> {> >Base b{ 300 };>// Using uniform initialization with {}> >b.print();> >return> 0;> }> |
>
>Produktion
44>
I ovenstående kode er værdien 300 uden for det gyldige interval for char, hvilket kan føre til udefineret adfærd og potentielt forkerte resultater. Compileren kan generere en advarsel eller fejl for denne situation, afhængigt af kompileringsindstillingerne.
Kode ved hjælp af ensartet initialisering {}
Ved at bruge ensartet initialisering med {} og initialisering af x med den angivne værdi a, vil compileren udføre strengere typekontrol og udstede en advarsel eller fejl under kompileringen, hvilket indikerer den indsnævrede konvertering fra int til char.
Her er kode med ensartet initialisering {} , som resulterer i en advarsel og dermed bedre at bruge
C++
#include> class> Base {> >char> x;> public>:> >Base(>char> a)> >: x{ a }> >{> >}> >void> print() { std::cout <<>static_cast><>int>>(x); }> };> int> main()> {> >Base b{ 300 };>// Using uniform initialization with {}> >b.print();> >return> 0;> }> |
>
>
main.cpp: In function ‘int main()’: main.cpp:17:17: error: narrowing conversion of ‘300’ from ‘int’ to ‘char’ [-Wnarrowing] 17 | Base b{ 300 }; // Using uniform initialization with {} | ^>