Initializatorių sąrašas naudojamas inicijuojant klasės duomenų narius. Inicijuojamų narių sąrašas nurodomas konstruktoriumi kaip kableliais atskirtas sąrašas, po kurio rašomas dvitaškis. Toliau pateikiamas pavyzdys, kuris naudoja inicializatorių sąrašą taško klasės x ir y inicijavimui.
Pavyzdys
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;> }> |
>
>Išvestis
x = 10, y = 15>
Aukščiau pateiktas kodas yra tik inicializatoriaus sąrašo sintaksės pavyzdys. Aukščiau pateiktame kode x ir y taip pat gali būti lengvai inicijuojami konstruktoriaus viduje. Tačiau yra situacijų, kai duomenų narių inicijavimas konstruktoriuje neveikia ir reikia naudoti inicijavimo sąrašą. Tokie atvejai yra tokie:
1. Nestatinių pastovių duomenų narių inicijavimui
const duomenų nariai turi būti inicijuoti naudojant Initializer List. Toliau pateiktame pavyzdyje t yra testo klasės const duomenų narys ir inicijuojamas naudojant inicijavimo sąrašą. Priežastis inicijuoti duomenų elementą const iniciatorių sąraše yra ta, kad konst duomenų nariui nėra skirta atskirai atmintis, ji yra sulankstyta simbolių lentelėje, dėl kurios turime jį inicijuoti iniciatorių sąraše.
Be to, tai yra parametrizuotas konstruktorius ir mums nereikia skambinti priskyrimo operatoriui, o tai reiškia, kad išvengiame vienos papildomos operacijos.
Pavyzdys
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; }> |
>
>Išvestis
10>
2. Dėl atskaitos narių inicijavimo
Nuorodos nariai turi būti inicijuoti naudojant inicijavimo sąrašą. Šiame pavyzdyje t yra testo klasės atskaitos narys ir inicijuojamas naudojant inicijavimo sąrašą.
Pavyzdys
C++
stygos c
// 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; }> |
>
>Išvestis
20 30>
3. Narių objektų, kurie neturi numatytojo konstruktoriaus, inicijavimui
Šiame pavyzdyje A klasės objektas a yra B klasės duomenų narys, o A neturi numatytojo konstruktoriaus. Inicijuoti turi būti naudojamas inicijavimo sąrašas.
Pavyzdys
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;> }> |
>
>Išvestis
A's Constructor called: Value of i: 10 B's Constructor called>
Jei A klasė turėjo ir numatytuosius, ir parametrinius konstruktorius, inicijavimo sąrašas nėra būtinas, jei norime inicijuoti naudojant numatytąjį konstruktorių, bet būtina inicijuoti naudojant parametrizuotą konstruktorių.
4. Bazinės klasės narių inicijavimui
Kaip ir 3 punkte, bazinės klasės parametrizuotas konstruktorius gali būti iškviestas tik naudojant inicijavimo sąrašą.
Pavyzdys
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;> }> |
>
>Išvestis
A's Constructor called: Value of i: 10 B's Constructor called>
5. Kai konstruktoriaus parametro pavadinimas yra toks pat kaip duomenų narys
Jei konstruktoriaus parametro pavadinimas yra toks pat kaip duomenų nario pavadinimas, duomenų narys turi būti inicijuotas naudojant šis rodyklė arba inicijavimo sąrašas. Toliau pateiktame pavyzdyje ir A() nario pavadinimas, ir parametro pavadinimas yra i.
Pavyzdys
C++
#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;> }> |
>
>Išvestis
10>
6. Dėl veiklos rezultatų
Geriau inicijuoti visus klasės kintamuosius inicijavimo sąraše, o ne priskirti reikšmes pagrindiniame tekste. Apsvarstykite šį pavyzdį:
Pavyzdys
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;> >}> };> |
>
>
Čia kompiliatorius atlieka šiuos veiksmus, kad sukurtų MyClass tipo objektą
1. Tipo konstruktorius pirmiausia iškviečiamas a.
2. Numatytasis konstrukcijos kintamasis
3. Tipo priskyrimo operatorius iškviečiamas MyClass() konstruktoriaus viduje, kad būtų galima priskirti
eilutę pokalbiui
variable = a;>
4. Ir tada galiausiai iškviečiamas Type destructor a, nes jis išeina iš taikymo srities.
Dabar apsvarstykite tą patį kodą naudodami „MyClass()“ konstruktorių su inicijavimo sąrašu
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> >}> };> |
>
>
Naudojant inicijavimo sąrašą, kompiliatorius atlieka šiuos veiksmus:
1. Tipo konstruktorius pirmiausia iškviečiamas a.
2. Tipo klasės parametrizuotas konstruktorius iškviečiamas inicijuoti: kintamąjį(a). Argumentai inicijavimo sąraše naudojami tiesiogiai kopijuoti konstravimo kintamąjį.
3. Iškviečiamas tipo naikintojas, nes jis nepatenka į taikymo sritį.
Kaip matome iš šio pavyzdžio, jei konstruktoriaus korpuse naudojame priskyrimą, yra trys funkcijų iškvietimai: konstruktorius + destruktorius + vienas priskyrimo operatoriaus skambutis. Ir jei mes naudojame inicijavimo sąrašą, yra tik du funkcijų iškvietimai: kopijavimo konstruktorius + naikintuvo iškvietimas. Šiame pranešime rasite pavyzdį šiuo klausimu.
Ši priskyrimo bausmė bus daug didesnė realiose programose, kur bus daug tokių kintamųjų. Ačiū ptr už šio punkto pridėjimą.
Parametras prieš vienodą inicijavimą C++
Geriau naudoti inicijavimo sąrašą su vienoda iniciacija {}, o ne parametrų inicijavimą (), kad išvengtumėte susiaurėjusių konversijų ir netikėto elgesio. Tai užtikrina griežtesnį tipo tikrinimą inicijavimo metu ir apsaugo nuo galimų susiaurėjusių konversijų
Kodas naudojant parametrų inicijavimą ()
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;> }> |
>
>Išvestis
44>
Aukščiau pateiktame kode 300 reikšmė nepatenka į galiojantį char diapazoną, todėl gali atsirasti neapibrėžtas elgesys ir galimi neteisingi rezultatai. Atsižvelgdamas į kompiliavimo nustatymus, kompiliatorius gali sugeneruoti įspėjimą arba klaidą šioje situacijoje.
Kodas naudojant vienodą inicijavimą {}
Naudodamas vienodą inicijavimą su {} ir inicijuodamas x su pateikta reikšme a, kompiliatorius atliks griežtesnį tipo tikrinimą ir kompiliavimo metu pateiks įspėjimą arba klaidą, nurodydamas susiaurėjantį konvertavimą iš int į char.
Čia yra kodas su vienoda iniciacija {} , dėl kurio gaunamas įspėjimas ir todėl jį geriau naudoti
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 {} | ^>