logo

Kopējiet Constructor programmā C++

Priekšnosacījums: Konstruktors C++ valodā

A kopiju konstruktors ir dalībnieka funkcija, kas inicializē objektu, izmantojot citu tās pašas klases objektu. Vienkārši izsakoties, konstruktors, kas izveido objektu, inicializējot to ar tās pašas klases objektu, kas ir izveidots iepriekš, ir pazīstams kā kopiju konstruktors .



Kopēšanas konstruktors tiek izmantots, lai inicializētu jaunizveidota objekta dalībniekus, kopējot jau esoša objekta dalībniekus.

Kopēšanas konstruktors izmanto atsauci uz tās pašas klases objektu kā argumentu.

Sample(Sample &t) { id=t.id; }>

Objekta elementu inicializācijas process, izmantojot kopiju konstruktoru, ir pazīstams kā kopijas inicializācija.



To sauc arī par inicializāciju pēc dalībnieka, jo kopiju konstruktors inicializē vienu objektu ar esošo objektu, kas abi pieder vienai un tai pašai klasei, pamatojoties uz katra dalībnieka kopiju.

Programmētājs var skaidri definēt kopēšanas konstruktoru. Ja programmētājs nedefinē kopēšanas konstruktoru, kompilators to izdara mūsu vietā.

Piemērs:



vārds
Kopēšanas konstruktora sintakse ar piemēru

Kopēšanas konstruktora sintakse

C++




#include> #include> using> namespace> std;> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >student(>int>,>char>[],>double>);> >student(student& t)>// copy constructor> >{> >rno = t.rno;> >strcpy>(name, t.name);> >fee = t.fee;> >}> >void> display();> };> student::student(>int> no,>char> n[],>double> f)> {> >rno = no;> >strcpy>(name, n);> >fee = f;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> int> main()> {> >student s(1001,>'Manjeet'>, 10000);> >s.display();> >student manjeet(s);>// copy constructor called> >manjeet.display();> >return> 0;> }>

>

>

Izvade

 1001 Manjeet 10000 1001 Manjeet 10000>

C++




#include> #include> using> namespace> std;> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >student(>int>,>char>[],>double>);> >student(student& t)>// copy constructor (member wise> >// initialization)> >{> >rno = t.rno;> >strcpy>(name, t.name);> >}> >void> display();> >void> disp() { cout << endl << rno <<>' '> << name; }> };> student::student(>int> no,>char> n[],>double> f)> {> >rno = no;> >strcpy>(name, n);> >fee = f;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> int> main()> {> >student s(1001,>'Manjeet'>, 10000);> >s.display();> >student manjeet(s);>// copy constructor called> >manjeet.disp();> >return> 0;> }>

>

>

Izvade

 1001 Manjeet 10000 1001 Manjeet>

Copy Constructor raksturojums

1. Kopēšanas konstruktors tiek izmantots, lai inicializētu jaunizveidota objekta dalībniekus, kopējot jau esoša objekta dalībniekus.

2. Kopēšanas konstruktors izmanto atsauci uz tās pašas klases objektu kā argumentu. Ja nododat objektu pēc vērtības kopēšanas konstruktorā, tas izraisītu rekursīvu izsaukumu pašam kopijas konstruktoram. Tas notiek tāpēc, ka vērtības nodošana ir saistīta ar kopijas izveidi, bet kopijas izveide ietver kopijas konstruktora izsaukšanu, kas noved pie bezgalīgas cilpas. Izmantojot atsauci, tiek novērsta šī atkārtošanās. Tāpēc mēs izmantojam objektu atsauci, lai izvairītos no bezgalīgiem izsaukumiem.

Sample(Sample &t) { id=t.id; }>

3. Objekta elementu inicializācijas process, izmantojot kopiju konstruktoru, ir pazīstams kā kopijas inicializācija.

4 . To sauc arī par inicializāciju pēc dalībnieka, jo kopiju konstruktors inicializē vienu objektu ar esošo objektu, kas abi pieder vienai klasei, pamatojoties uz kopiju katram dalībniekam.

5. Programmētājs var skaidri definēt kopēšanas konstruktoru. Ja programmētājs nedefinē kopēšanas konstruktoru, kompilators to izdara mūsu vietā.

Piemērs:

C++


iterējoša karte java



// C++ program to demonstrate the working> // of a COPY CONSTRUCTOR> #include> using> namespace> std;> class> Point {> private>:> >int> x, y;> public>:> >Point(>int> x1,>int> y1)> >{> >x = x1;> >y = y1;> >}> >// Copy constructor> >Point(>const> Point& p1)> >{> >x = p1.x;> >y = p1.y;> >}> >int> getX() {>return> x; }> >int> getY() {>return> y; }> };> int> main()> {> >Point p1(10, 15);>// Normal constructor is called here> >Point p2 = p1;>// Copy constructor is called here> >// Let us access values assigned by constructors> >cout <<>'p1.x = '> << p1.getX()> ><<>', p1.y = '> << p1.getY();> >cout <<>' p2.x = '> << p2.getX()> ><<>', p2.y = '> << p2.getY();> >return> 0;> }>

>

>

Izvade

p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>

Kopēšanas konstruktoru veidi

1. Noklusējuma kopēšanas konstruktors

Netieši definēts kopiju konstruktors kopēs objekta pamatus un elementus tādā pašā secībā, kādā konstruktors inicializēs objekta pamatnes un elementus.

C++




// Implicit copy constructor Calling> #include> using> namespace> std;> class> Sample {> >int> id;> public>:> >void> init(>int> x) { id = x; }> >void> display() { cout << endl <<>'ID='> << id; }> };> int> main()> {> >Sample obj1;> >obj1.init(10);> >obj1.display();> >// Implicit Copy Constructor Calling> >Sample obj2(obj1);>// or obj2=obj1;> >obj2.display();> >return> 0;> }>

>

>

Izvade

 ID=10 ID=10>

2. Lietotāja definēts kopiju konstruktors

Lietotāja definēts kopijas konstruktors parasti ir nepieciešams, ja objektam pieder norādes vai nekoplietojamas atsauces, piemēram, uz failu, un tādā gadījumā ir jāieraksta arī iznīcinātājs un piešķiršanas operators.

C++




// Explicitly copy constructor Calling> #include> using> namespace> std;> class> Sample {> >int> id;> public>:> >void> init(>int> x) { id = x; }> >Sample() {}>// default constructor with empty body> >Sample(Sample& t)>// copy constructor> >{> >id = t.id;> >}> >void> display() { cout << endl <<>'ID='> << id; }> };> int> main()> {> >Sample obj1;> >obj1.init(10);> >obj1.display();> >Sample obj2(> >obj1);>// or obj2=obj1; copy constructor called> >obj2.display();> >return> 0;> }>

>

>

Izvade

 ID=10 ID=10>

C++




// C++ Programt to demonstrate the student details> #include> #include> using> namespace> std;> class> student {> >int> rno;> >string name;> >double> fee;> public>:> >student(>int>, string,>double>);> >student(student& t)>// copy constructor> >{> >rno = t.rno;> >name = t.name;> >fee = t.fee;> >}> >void> display();> };> student::student(>int> no, string n,>double> f)> {> >rno = no;> >name = n;> >fee = f;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> int> main()> {> >student s(1001,>'Ram'>, 10000);> >s.display();> >student ram(s);>// copy constructor called> >ram.display();> >return> 0;> }>

virknes vērtība
>

>

Izvade

 1001 Ram 10000 1001 Ram 10000>

Kad tiek izsaukts kopiju konstruktors?

Programmā C++ Copy Constructor var tikt izsaukts šādos gadījumos:

  • Kad klases objekts tiek atgriezts pēc vērtības.
  • Kad klases objekts tiek nodots (funkcijai) pēc vērtības kā arguments.
  • Ja objekts ir konstruēts, pamatojoties uz citu tās pašas klases objektu.
  • Kad kompilators ģenerē pagaidu objektu.

Tomēr nav garantēts, ka visos šajos gadījumos tiks izsaukts kopiju konstruktors, jo C++ standarts ļauj kompilatoram noteiktos gadījumos optimizēt kopiju, piemēram, atdeves vērtības optimizācija (dažreiz saukts par RVO).

Kopēt Elision

Kopiju elision gadījumā kompilators neļauj izveidot papildu kopijas, kas ļauj ietaupīt vietu un uzlabot programmas sarežģītību (gan laikā, gan telpā); Tādējādi kods tiek optimizēts.

Piemērs:

C++




// C++ program to demonstrate> // the working of copy elision> #include> using> namespace> std;> class> GFG {> public>:> >void> print() { cout <<>' GFG!'>; }> };> int> main()> {> >GFG G;> >for> (>int> i = 0; i <= 2; i++) {> >G.print();> >cout <<>' '>;> >}> >return> 0;> }>

>

>

Izvade

 GFG! GFG! GFG!>

Tagad kompilatoram ir jāizlemj, ko tas vēlas drukāt. Tas var izdrukāt iepriekš minēto izvadi vai arī drukāt 1. vai 2. gadījumu, un tas ir tas, kas Atdeves vērtības optimizācija ir. Vienkāršiem vārdiem sakot, RVO ir paņēmiens, kas dod kompilatoram papildu pilnvaras, lai pārtrauktu izveidoto pagaidu objektu, kā rezultātā tiek mainīta galīgās programmas novērojamā uzvedība/īpašības.

1. gadījums:

GFG! GFG!>

2. gadījums:

GFG!>

Kad ir nepieciešams lietotāja definēts kopiju konstruktors?

Ja mēs nedefinējam savu kopiju konstruktoru, C++ kompilators izveido noklusējuma kopijas konstruktoru katrai klasei, kas veic kopiju starp objektiem. Kompilatora izveidotais kopiju konstruktors kopumā darbojas labi. Mums ir jādefinē savs kopijas konstruktors tikai tad, ja objektam ir norādes vai kāds resursa izpildlaika sadalījums, piemēram, faila rokturis , tīkla savienojums utt.

Noklusējums konstruktors veic tikai seklu kopiju.

sekla kopija C++ valodā

Dziļā kopēšana ir iespējama tikai ar lietotāja definētu kopiju konstruktoru. Lietotāja definētā kopiju konstruktorā mēs pārliecināmies, ka nokopēto objektu norādes (vai atsauces) norāda uz jaunām atmiņas vietām.

Dziļā kopēšana programmā C++

Kopēt konstruktoru pret uzdevumu operatoru

Galvenā atšķirība starp kopēšanas konstruktoru un piešķiršanas operatoru ir tāda, ka kopēšanas konstruktors izveido jaunu atmiņas krātuvi katru reizi, kad tā tiek izsaukta, kamēr piešķiršanas operators neizveido jaunu atmiņas krātuvi.

Kurš no šiem diviem apgalvojumiem izsauc kopijas konstruktoru un kurš izsauc piešķiršanas operatoru?

MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = t1; // -----> (2)>> 

Kopiju konstruktors tiek izsaukts, kad no esoša objekta tiek izveidots jauns objekts kā esošā objekta kopija. Piešķiršanas operators tiek izsaukts, kad jau inicializētam objektam tiek piešķirta jauna vērtība no cita esoša objekta. Iepriekš minētajā piemērā (1) izsauc kopēšanas konstruktoru un (2) izsauc piešķiršanas operatoru. Skatiet šo, lai iegūtu sīkāku informāciju.

Piemērs — klase, kur nepieciešams kopēšanas konstruktors

Tālāk ir sniegta pilnīga C++ programma, lai demonstrētu Copy konstruktora izmantošanu. Nākamajā String klasē mums ir jāieraksta kopijas konstruktors.

Piemērs:

C++


c programmēšanas piemēru programmas



// C++ program to demonstrate the> // Working of Copy constructor> #include> #include> using> namespace> std;> class> String {> private>:> >char>* s;> >int> size;> public>:> >String(>const> char>* str = NULL);>// constructor> >~String() {>delete>[] s; }>// destructor> >String(>const> String&);>// copy constructor> >void> print()> >{> >cout << s << endl;> >}>// Function to print string> >void> change(>const> char>*);>// Function to change> };> // In this the pointer returns the CHAR ARRAY> // in the same sequence of string object but> // with an additional null pointer ' '> String::String(>const> char>* str)> {> >size =>strlen>(str);> >s =>new> char>[size + 1];> >strcpy>(s, str);> }> void> String::change(>const> char>* str)> {> >delete>[] s;> >size =>strlen>(str);> >s =>new> char>[size + 1];> >strcpy>(s, str);> }> String::String(>const> String& old_str)> {> >size = old_str.size;> >s =>new> char>[size + 1];> >strcpy>(s, old_str.s);> }> int> main()> {> >String str1(>'GeeksQuiz'>);> >String str2 = str1;> >str1.print();>// what is printed ?> >str2.print();> >str2.change(>'techcodeview.com'>);> >str1.print();>// what is printed now ?> >str2.print();> >return> 0;> }>

>

Izvade

GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>

Kāda būtu problēma, ja mēs noņemtu kopiju konstruktoru no iepriekš minētā koda?

Ja mēs noņemsim kopēšanas konstruktoru no iepriekš minētās programmas, mēs nesaņemsim gaidīto rezultātu. Str2 veiktās izmaiņas atspoguļojas arī str1, kas nekad nav gaidāms.

C++




#include> #include> using> namespace> std;> class> String {> private>:> >char>* s;> >int> size;> public>:> >String(>const> char>* str = NULL);>// constructor> >~String() {>delete>[] s; }>// destructor> >void> print() { cout << s << endl; }> >void> change(>const> char>*);>// Function to change> };> String::String(>const> char>* str)> {> >size =>strlen>(str);> >s =>new> char>[size + 1];> >strcpy>(s, str);> }> // In this the pointer returns the CHAR ARRAY> // in the same sequence of string object but> // with an additional null pointer ' '> void> String::change(>const> char>* str) {>strcpy>(s, str); }> int> main()> {> >String str1(>'GeeksQuiz'>);> >String str2 = str1;> >str1.print();>// what is printed ?> >str2.print();> >str2.change(>'techcodeview.com'>);> >str1.print();>// what is printed now ?> >str2.print();> >return> 0;> }>

>

>

Izvade:

GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>

Vai varam padarīt kopiju konstruktoru privātu?

Jā, kopiju konstruktoru var padarīt privātu. Kad mēs klasē padarām kopijas konstruktoru privātu, šīs klases objekti kļūst nekopējami. Tas ir īpaši noderīgi, ja mūsu klasē ir norādes vai dinamiski piešķirti resursi. Šādās situācijās mēs varam vai nu uzrakstīt savu kopiju konstruktoru, piemēram, iepriekš minētajā virknes piemērā, vai izveidot privātu kopijas konstruktoru, lai lietotāji izpildes laikā saņemtu kompilatora kļūdas, nevis pārsteigumus.

Kāpēc arguments kopijas konstruktoram ir jānodod kā atsauce?

Kopiju konstruktors tiek izsaukts, kad objekts tiek nodots pēc vērtības. Pati kopēšanas konstruktors ir funkcija. Tātad, ja mēs nododam argumentu pēc vērtības kopēšanas konstruktorā, tiks veikts izsaukums kopijas konstruktoram, lai izsauktu kopijas konstruktoru, kas kļūst par nebeidzamu izsaukumu ķēdi. Tāpēc kompilators neļauj parametrus nodot pēc vērtības.

Kāpēc argumentu kopiju konstruktoram vajadzētu būt const?

Viens no pāriešanas iemesliem konst atsauce ir, ka mums vajadzētu izmantot konst C++, kur vien iespējams, lai objekti netiktu nejauši pārveidoti. Tas ir viens labs iemesls, lai nodotu atsauci kā konst , taču tajā ir kas vairāk nekā Kāpēc argumentu kopiju konstruktoram vajadzētu konst?