Initialiseringsliste brukes til å initialisere datamedlemmene i en klasse. Listen over medlemmer som skal initialiseres er indikert med konstruktør som en kommaseparert liste etterfulgt av et kolon. Følgende er et eksempel som bruker initialiseringslisten til å 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;> }> |
>
>Produksjon
x = 10, y = 15>
Koden ovenfor er bare et eksempel for syntaks for Initializer-listen. I koden ovenfor kan x og y også enkelt initialiseres inne i konstruktøren. Men det er situasjoner der initialisering av datamedlemmer inne i konstruktøren ikke fungerer og initialiseringsliste må brukes. Følgende er slike tilfeller:
1. For initialisering av ikke-statiske konstdatamedlemmer
const data medlemmer må initialiseres ved hjelp av Initializer List. I det følgende eksempelet er t et const datamedlem av Test-klassen og initialiseres ved hjelp av Initializer List. Grunnen til å initialisere const data-medlemmet i initialiseringslisten er fordi det ikke er tildelt minne separat for const data-medlemmet, det er foldet inn i symboltabellen på grunn av at vi må initialisere det i initialiseringslisten.
Det er også en parameterisert konstruktør, og vi trenger ikke å ringe oppdragsoperatøren, noe som betyr at vi unngår én ekstra operasjon.
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; }> |
>
>Produksjon
10>
2. For initialisering av referansemedlemmer
Referansemedlemmer må initialiseres ved hjelp av initialiseringslisten. I det følgende eksemplet er t et referansemedlem i Test-klassen og initialiseres ved hjelp av Initializer List.
Eksempel
C++
nettverkstopologi
// 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; }> |
>
>Produksjon
20 30>
3. For initialisering av medlemsobjekter som ikke har en standard konstruktør
I følgende eksempel er et objekt a i klasse A et datamedlem av klasse B, og A har ikke en standardkonstruktør. Initialiseringsliste må brukes til å 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;> }> |
>
>Produksjon
A's Constructor called: Value of i: 10 B's Constructor called>
Hvis klasse A hadde både standard og parameteriserte konstruktører, er ikke Initializer List et must hvis vi ønsker å initialisere en ved å bruke standardkonstruktøren, men det er nødvendig for å initialisere en ved å bruke den parameteriserte konstruktøren.
4. For initialisering av basisklassemedlemmer
I likhet med punkt 3 kan den parameteriserte konstruktøren til basisklassen kun kalles ved å bruke 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;> }> |
>
>Produksjon
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, må datamedlemmet initialiseres enten ved hjelp av denne pekeren eller Initialiseringsliste. I det følgende eksempelet 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;> }> |
>
>Produksjon
10>
6. Av ytelsesgrunner
Det er bedre å initialisere alle klassevariabler i Initialiseringslisten i stedet for å tilordne verdier inne i kroppen. Tenk på 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 kompilatoren følgende trinn for å lage et objekt av typen MyClass
1. Types konstruktør kalles først for a.
2. Standard konstruksjonsvariabel
3. Tilordningsoperatøren av Type kalles inne i brødteksten til MyClass()-konstruktøren for å tildele
variable = a;>
4. Og så til slutt blir destructor av Type kalt for en siden den går utenfor scope.
Vurder nå den samme koden 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 initialiseringslisten følges følgende trinn av kompilatoren:
1. Types konstruktør kalles først for a.
2. Parameterisert konstruktør av Type-klassen kalles for å initialisere: variabel(a). Argumentene i initialiseringslisten brukes til å kopiere konstruksjonsvariabelen direkte.
3. Destruktoren av Type kalles for a siden den går utenfor scope.
Som vi kan se fra dette eksemplet, hvis vi bruker tildeling inne i konstruktørkroppen, er det tre funksjonskall: konstruktør + destruktor + ett tilleggstildelingsoperatørkall. Og hvis vi bruker Initializer List er det bare to funksjonskall: kopi konstruktør + destruktorkall. Se dette innlegget for et løpende eksempel på dette punktet.
Denne tildelingsstraffen vil være mye mer i reelle applikasjoner der det vil være mange slike variabler. Takk til ptr for å legge til dette punktet.
Parameter vs enhetlig initialisering i C++
Det er bedre å bruke en initialiseringsliste med enhetlig initialisering {} i stedet for parameterinitialisering () for å unngå problemet med begrensende konverteringer og uventet oppførsel. Det gir strengere typekontroll under initialisering og forhindrer potensielle innsnevrede konverteringer
Kode ved hjelp av 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;> }> |
>
>Produksjon
44>
I koden ovenfor er verdien 300 utenfor det gyldige området for char, noe som kan føre til udefinert oppførsel og potensielt feil resultater. Kompilatoren kan generere en advarsel eller feil for denne situasjonen, avhengig av kompileringsinnstillingene.
Kode med enhetlig initialisering {}
Ved å bruke enhetlig initialisering med {} og initialisering av x med den angitte verdien a, vil kompilatoren utføre strengere typekontroll og gi en advarsel eller feil under kompilering, som indikerer den innsnevrede konverteringen fra int til char.
Her er kode med uniform initialisering {} , som resulterer i en advarsel og dermed bedre å bruke
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 {} | ^>