Inicializētāju saraksts tiek izmantots, lai inicializētu klases datu elementus. Inicializējamo dalībnieku saraksts ir norādīts ar konstruktoru kā ar komatu atdalītu sarakstu, kam seko kols. Tālāk ir sniegts piemērs, kas izmanto inicializatoru sarakstu, lai inicializētu punktu klases x un y.
Piemērs
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;> }> |
>
>Izvade
x = 10, y = 15>
Iepriekš minētais kods ir tikai inicializatoru saraksta sintakses piemērs. Iepriekš minētajā kodā x un y var viegli inicializēt arī konstruktora iekšpusē. Bet ir situācijas, kad datu dalībnieku inicializācija konstruktorā nedarbojas, un ir jāizmanto inicializatoru saraksts. Šādi gadījumi ir šādi:
1. Non-static const datu dalībnieku inicializācijai
const datu dalībnieki ir jāinicializē, izmantojot inicializatoru sarakstu. Nākamajā piemērā t ir testa klases const datu dalībnieks, un tas tiek inicializēts, izmantojot inicializatoru sarakstu. Iemesls datu elementa const inicializācijai inicializētāju sarakstā ir tāpēc, ka datu dalībniekam const nav atsevišķi atvēlēta atmiņa, tas ir salocīts simbolu tabulā, kā dēļ mums tas ir jāinicializē inicializētāju sarakstā.
Turklāt tas ir parametrizēts konstruktors, un mums nav jāizsauc piešķiršanas operators, kas nozīmē, ka mēs izvairāmies no vienas papildu darbības.
Piemērs
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; }> |
>
>Izvade
10>
2. Atsauces biedru inicializācijai
Atsauces locekļi ir jāinicializē, izmantojot inicializatoru sarakstu. Nākamajā piemērā t ir pārbaudes klases atsauces dalībnieks, un tas tiek inicializēts, izmantojot inicializatoru sarakstu.
Piemērs
C++
pavasara mākonis
// 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; }> |
>
>Izvade
20 30>
3. Dalībnieku objektu inicializācijai, kuriem nav noklusējuma konstruktora
Nākamajā piemērā A klases objekts a ir klases B datu dalībnieks, un A nav noklusējuma konstruktora. Inicializētāju saraksts ir jāizmanto, lai inicializētu a.
Piemērs
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;> }> |
>
>Izvade
A's Constructor called: Value of i: 10 B's Constructor called>
Ja A klasei bija gan noklusējuma, gan parametrizēti konstruktori, inicializatoru saraksts nav obligāts, ja vēlamies inicializēt a, izmantojot noklusējuma konstruktoru, bet tas ir obligāts, izmantojot parametrizēto konstruktoru.
4. Bāzes klases dalībnieku inicializācijai
Tāpat kā 3. punktu, bāzes klases parametrizēto konstruktoru var izsaukt tikai, izmantojot inicializatoru sarakstu.
Piemērs
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;> }> |
>
>Izvade
A's Constructor called: Value of i: 10 B's Constructor called>
5. Ja konstruktora parametra nosaukums ir tāds pats kā datu dalībnieka nosaukums
Ja konstruktora parametra nosaukums ir tāds pats kā datu elementa nosaukums, datu dalībnieks ir jāinicializē, izmantojot vai nu šo rādītāju vai inicializatoru saraksts. Nākamajā piemērā gan A() dalībnieka nosaukums, gan parametra nosaukums ir i.
Piemērs
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;> }> |
>
>
atribūta kļūda pythonIzvade
10>
6. Veiktspējas iemeslu dēļ
Labāk ir inicializēt visus klases mainīgos Initializer List, nevis piešķirt vērtības pamattekstā. Apsveriet šādu piemēru:
Piemērs
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;> >}> };> |
>
>
Šeit kompilators veic šādas darbības, lai izveidotu MyClass tipa objektu
1. Tipa konstruktors vispirms tiek izsaukts a.
2. Noklusējuma konstrukcijas mainīgais
3. Tipa piešķiršanas operators tiek izsaukts konstruktora MyClass() korpusā, lai piešķirtu
variable = a;>
4. Un tad visbeidzot tiek izsaukts Type destructor, jo tas iziet ārpus darbības jomas.
Tagad apsveriet to pašu kodu ar MyClass() konstruktoru ar inicializētāju sarakstu
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> >}> };> |
>
>
Izmantojot inicializatoru sarakstu, kompilators veic šādas darbības:
1. Tipa konstruktors vispirms tiek izsaukts a.
2. Tipa klases parametrizētais konstruktors tiek izsaukts, lai inicializētu: mainīgo(a). Argumenti inicializatoru sarakstā tiek izmantoti, lai tieši kopētu konstruējamo mainīgo.
3. Tiek izsaukts tipa iznīcinātājs, jo tas ir ārpus darbības jomas.
Kā redzams no šī piemēra, ja mēs izmantojam piešķiršanu konstruktora pamattekstā, ir trīs funkciju izsaukumi: konstruktors + destruktors + viens papildinājuma piešķiršanas operatora izsaukums. Un, ja mēs izmantojam inicializatoru sarakstu, ir tikai divi funkciju izsaukumi: kopēt konstruktoru + iznīcinātāja izsaukums. Skatiet šo ziņu, lai iegūtu piemēru par šo punktu.
Šis piešķiršanas sods būs daudz lielāks reālos lietojumos, kur būs daudz šādu mainīgo. Pateicoties ptr par šī punkta pievienošanu.
Parametrs pret vienotu inicializāciju C++
Labāk ir izmantot inicializācijas sarakstu ar vienotu inicializēšanu {}, nevis parametru inicializāciju (), lai izvairītos no reklāmguvumu samazināšanās un neparedzētas darbības. Tas nodrošina stingrāku tipa pārbaudi inicializācijas laikā un novērš iespējamus sašaurinošus reklāmguvumus
Kods, izmantojot parametru inicializēšanu ()
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;> }> |
>
>Izvade
44>
Iepriekš minētajā kodā vērtība 300 ir ārpus char derīgā diapazona, kas var izraisīt nedefinētu darbību un, iespējams, nepareizus rezultātus. Atkarībā no kompilācijas iestatījumiem kompilators šajā situācijā var ģenerēt brīdinājumu vai kļūdu.
Kods, izmantojot vienotu inicializēšanu {}
Izmantojot vienotu inicializēšanu ar {} un inicializējot x ar norādīto vērtību a, kompilators veiks stingrāku tipa pārbaudi un kompilācijas laikā izdos brīdinājumu vai kļūdu, norādot uz sašaurinošu pārveidi no int uz char.
Šeit ir kods ar vienotu inicializāciju {} , kas rada brīdinājumu un tādējādi labāk lietojams
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 {} | ^>