Initializer List -luetteloa käytetään luokan datajäsenten alustamiseen. Alustettavien jäsenten luettelo on merkitty konstruktorilla pilkuilla eroteltuna luettelona, jota seuraa kaksoispiste. Seuraavassa on esimerkki, joka käyttää alustusluetteloa pisteluokan x:n ja y:n alustamiseen.
Esimerkki
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;> }> |
>
>Lähtö
x = 10, y = 15>
Yllä oleva koodi on vain esimerkki Initializer-luettelon syntaksista. Yllä olevassa koodissa x ja y voidaan myös helposti alustaa konstruktorin sisällä. Mutta on tilanteita, joissa datajäsenten alustus konstruktorissa ei toimi ja Initializer List -luetteloa on käytettävä. Tällaisia tapauksia ovat seuraavat:
1. Ei-staattisten vakiotietojäsenten alustamiseen
const-datajäsenet on alustettava Initializer List -toiminnolla. Seuraavassa esimerkissä t on Test-luokan const-datajäsen ja se alustetaan Initializer List -toiminnolla. Syy const-datajäsenen alustamiseen alustuslistassa on se, että const-datajäsenelle ei ole varattu erikseen muistia, se on taitettu symbolitaulukossa, minkä vuoksi meidän on alustettava se alustuslistassa.
Lisäksi se on parametroitu konstruktori, eikä meidän tarvitse kutsua määritysoperaattoria, mikä tarkoittaa, että vältämme yhden ylimääräisen toiminnon.
Esimerkki
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; }> |
>
>Lähtö
10>
2. Viitejäsenten alustamiseen
Viitejäsenet on alustettava Initializer List -luettelon avulla. Seuraavassa esimerkissä t on Test-luokan referenssijäsen ja se alustetaan Initializer List -luettelon avulla.
Esimerkki
C++
onclick js
// 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; }> |
>
>Lähtö
20 30>
3. Sellaisten jäsenobjektien alustamiseen, joilla ei ole oletuskonstruktoria
Seuraavassa esimerkissä luokan A objekti a on luokan B tietojäsen, eikä A:lla ole oletuskonstruktoria. Alustusluetteloa on käytettävä alustamiseen a.
Esimerkki
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;> }> |
>
>Lähtö
A's Constructor called: Value of i: 10 B's Constructor called>
Jos luokassa A oli sekä oletus- että parametroituja konstruktoreita, Initializer List ei ole pakollinen, jos haluamme alustaa a oletuskonstruktorin avulla, mutta se on alustettava parametroidulla konstruktorilla.
4. Perusluokan jäsenten alustamiseen
Kuten kohta 3, perusluokan parametroitua konstruktoria voidaan kutsua vain Initializer List -luettelon avulla.
Esimerkki
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;> }> |
>
>Lähtö
A's Constructor called: Value of i: 10 B's Constructor called>
5. Kun rakentajan parametrin nimi on sama kuin datajäsen
Jos rakentajan parametrin nimi on sama kuin datajäsenen nimi, datajäsen on alustettava joko käyttämällä tämä osoitin tai Initializer List. Seuraavassa esimerkissä sekä jäsenen nimi että parametrin nimi A():lle on i.
Esimerkki
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;> }> |
>
>Lähtö
10>
6. Suorituskykyyn liittyvistä syistä
On parempi alustaa kaikki luokkamuuttujat Initializer Listissa sen sijaan, että määrittäisit arvot rungon sisällä. Harkitse seuraavaa esimerkkiä:
Esimerkki
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;> >}> };> |
>
>
Tässä kääntäjä noudattaa seuraavia vaiheita luodakseen MyClass-tyypin objektin
1. Tyypin konstruktoria kutsutaan ensin a:lle.
2. Oletusrakennemuuttuja
3. Tyypin osoitusoperaattoria kutsutaan MyClass()-konstruktorin rungossa määritettäväksi
variable = a;>
4. Ja sitten lopuksi tyypin destructor kutsutaan a, koska se menee soveltamisalan ulkopuolelle.
Harkitse nyt samaa koodia MyClass()-konstruktorilla, jossa on 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> >}> };> |
>
>
Initializer List -luettelossa kääntäjä seuraa seuraavia vaiheita:
1. Tyypin konstruktoria kutsutaan ensin a:lle.
2. Type-luokan parametroitua konstruktoria kutsutaan alustamaan: muuttuja(a). Alustusluettelon argumentteja käytetään rakennusmuuttujan kopioimiseen suoraan.
3. Tyypin tuhoajaa kutsutaan a, koska se menee soveltamisalan ulkopuolelle.
Kuten tästä esimerkistä nähdään, jos käytämme osoitusta konstruktorirungon sisällä, funktiokutsuja on kolme: konstruktori + destruktori + yksi lisäystehtäväoperaattorikutsu. Ja jos käytämme Initializer List -toimintoa, on vain kaksi funktiokutsua: kopioi rakentaja + tuhoajakutsu. Katso tästä viestistä toimiva esimerkki tästä kohdasta.
Tämä luovutusrangaistus on paljon suurempi todellisissa sovelluksissa, joissa on monia tällaisia muuttujia. Kiitokset ptr tämän kohdan lisäämisestä.
Parametri vs yhtenäinen alustus C++:ssa
Parametrien alustuksen () sijaan on parempi käyttää alustusluetteloa, jossa on yhtenäinen alustus {}, jotta vältetään konversioiden kapeneminen ja odottamaton toiminta. Se tarjoaa tiukemman tyyppitarkistuksen alustuksen aikana ja estää mahdollisia kapenevia muunnoksia
Koodi käyttämällä parametrien alustusta ()
java-kuplalajittelu
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;> }> |
>
>Lähtö
44>
Yllä olevassa koodissa arvo 300 on kelvollisen char-alueen ulkopuolella, mikä voi johtaa määrittelemättömään toimintaan ja mahdollisesti virheellisiin tuloksiin. Kääntäjä saattaa tuottaa varoituksen tai virheen tästä tilanteesta riippuen käännösasetuksista.
Koodi käyttäen yhtenäistä alustusta {}
Käyttämällä yhtenäistä alustusta {}:n kanssa ja alustamalla x:n annetulla arvolla a kääntäjä suorittaa tiukemman tyyppitarkistuksen ja antaa kääntämisen aikana varoituksen tai virheen, joka ilmaisee kaventuvan muunnoksen int:stä chariksi.
Tässä on koodi yhtenäisellä alustuksella {} , joka aiheuttaa varoituksen ja on siten parempi käyttää
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 {} | ^>