logo

Nukopijuokite Constructor į C++

Būtina sąlyga: Konstruktorius C++ kalba

A kopijavimo konstruktorius yra nario funkcija, kuri inicijuoja objektą naudojant kitą tos pačios klasės objektą. Paprastais žodžiais tariant, konstruktorius, kuris sukuria objektą inicijuodamas jį tos pačios klasės objektu, kuris buvo sukurtas anksčiau, yra žinomas kaip kopijavimo konstruktorius .



Kopijavimo konstruktorius naudojamas naujai sukurto objekto nariams inicijuoti, nukopijuojant jau esamo objekto narius.

Kopijavimo konstruktorius kaip argumentą laiko nuorodą į tos pačios klasės objektą.

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

Objekto narių inicijavimo procesas naudojant kopijavimo konstruktorių yra žinomas kaip kopijavimo inicijavimas.



Jis taip pat vadinamas nario inicijavimu, nes kopijavimo konstruktorius inicijuoja vieną objektą esamu objektu, kuris abu priklauso tai pačiai klasei, remiantis kiekvieno nario kopija.

Programuotojas gali aiškiai apibrėžti kopijavimo konstruktorių. Jei programuotojas neapibrėžia kopijavimo konstruktoriaus, kompiliatorius tai padaro už mus.

Pavyzdys:



nelygus rąstas
Kopijavimo konstruktoriaus sintaksė su pavyzdžiu

Kopijavimo konstruktoriaus sintaksė

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;> }>

>

>

Išvestis

 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;> }>

>

>

Išvestis

 1001 Manjeet 10000 1001 Manjeet>

Copy Constructor charakteristikos

1. Kopijavimo konstruktorius naudojamas naujai sukurto objekto nariams inicijuoti, nukopijuojant jau esamo objekto narius.

2. Kopijavimo konstruktorius kaip argumentą laiko nuorodą į tos pačios klasės objektą. Jei kopijos konstruktoriuje perduodate objektą pagal vertę, tai sukels rekursinį skambutį pačiam kopijavimo konstruktoriui. Taip atsitinka todėl, kad perduodant vertę reikia padaryti kopiją, o darant kopiją – iškviesti kopijavimo konstruktorių, o tai veda į begalinę kilpą. Naudojant nuorodą išvengiama šios rekursijos. Taigi mes naudojame objektų nuorodą, kad išvengtume begalinių skambučių.

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

3. Objekto narių inicijavimo procesas naudojant kopijavimo konstruktorių yra žinomas kaip kopijavimo inicijavimas.

4 . Jis taip pat vadinamas nario inicijavimu, nes kopijavimo konstruktorius inicijuoja vieną objektą esamu objektu, kuris abu priklauso tai pačiai klasei, remiantis kiekvieno nario kopija.

5. Programuotojas gali aiškiai apibrėžti kopijavimo konstruktorių. Jei programuotojas neapibrėžia kopijavimo konstruktoriaus, kompiliatorius tai padaro už mus.

Pavyzdys:

C++




// 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;> }>

>

>

Išvestis

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

Kopijavimo konstruktorių tipai

1. Numatytasis kopijavimo konstruktorius

Netiesiogiai apibrėžtas kopijavimo konstruktorius nukopijuos objekto pagrindus ir elementus ta pačia tvarka, kokia konstruktorius inicijuotų objekto pagrindus ir 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;> }>

>

>

Išvestis

 ID=10 ID=10>

2. User Defined Copy Constructor

Vartotojo apibrėžtas kopijos konstruktorius paprastai reikalingas, kai objektui priklauso rodyklės arba nebendrinami nuorodos, pvz., į failą, tokiu atveju taip pat turėtų būti parašytas naikintojas ir priskyrimo operatorius.

C++


išpakavimas naudojant linux



// 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;> }>

>

>

Išvestis

 ID=10 ID=10>

C++


pakeisti eilutę java



// 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;> }>

>

>

Išvestis

 1001 Ram 10000 1001 Ram 10000>

Kada vadinamas kopijavimo konstruktorius?

C++ kalboje Copy Constructor gali būti iškviestas šiais atvejais:

  • Kai klasės objektas grąžinamas pagal vertę.
  • Kai klasės objektas perduodamas (funkcijai) pagal reikšmę kaip argumentą.
  • Kai objektas konstruojamas remiantis kitu tos pačios klasės objektu.
  • Kai kompiliatorius sukuria laikiną objektą.

Tačiau negarantuojama, kad visais šiais atvejais bus iškviestas kopijavimo konstruktorius, nes C++ standartas leidžia kompiliatoriui tam tikrais atvejais optimizuoti kopiją, pavyzdžiui, grąžinamos vertės optimizavimas (kartais vadinamas RVO).

Kopijuoti Elision

Kopijavimo elision atveju kompiliatorius neleidžia daryti papildomų kopijų, todėl sutaupoma vietos ir padidinamas programos sudėtingumas (tiek laikas, tiek erdvė); Taigi kodas yra labiau optimizuotas.

Pavyzdys:

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;> }>

>

>

Išvestis

 GFG! GFG! GFG!>

Dabar kompiliatorius turi nuspręsti, ką jis nori spausdinti. Jis gali išspausdinti aukščiau pateiktą išvestį arba 1 arba 2 atvejį žemiau, ir štai kas Grąžinimo vertės optimizavimas yra. Paprastais žodžiais, RVO yra technika, suteikianti kompiliatoriui papildomos galios nutraukti sukurtą laikiną objektą, dėl kurio pasikeičia stebimas galutinės programos elgesys / charakteristikos.

1 atvejis:

GFG! GFG!>

2 atvejis:

GFG!>

Kada reikalingas vartotojo apibrėžtas kopijavimo konstruktorius?

Jei neapibrėžiame savo kopijos konstruktoriaus, C++ kompiliatorius sukuria numatytąjį kiekvienos klasės kopijos konstruktorių, kuris kopijuoja tarp objektų. Kompiliatoriaus sukurtas kopijos konstruktorius apskritai veikia gerai. Turime apibrėžti savo kopijos konstruktorių tik tuo atveju, jei objektas turi rodykles arba bet kokį resurso vykdymo laiką, pvz. failo rankena , tinklo ryšį ir pan.

Numatytoji konstruktorius daro tik seklią kopiją.

sekli kopija C++

jquery tėvas

Gilus kopijavimas galimas tik naudojant vartotojo apibrėžtą kopijavimo konstruktorių. Vartotojo apibrėžtame kopijų konstruktoriuje užtikriname, kad nukopijuotų objektų rodyklės (arba nuorodos) nukreiptų į naujas atminties vietas.

Gilus kopijavimas C++

Kopijuoti konstruktorių prieš priskyrimo operatorių

Pagrindinis skirtumas tarp Copy Constructor ir Assignment Operator yra tas, kad kopijavimo konstruktorius sukuria naują atminties saugyklą kiekvieną kartą, kai ji iškviečiama, o priskyrimo operatorius nesukuria naujos atminties saugyklos.

Kuris iš šių dviejų teiginių iškviečia kopijavimo konstruktorių, o kuris – priskyrimo operatorių?

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

Kopijavimo konstruktorius iškviečiamas, kai iš esamo objekto sukuriamas naujas objektas kaip esamo objekto kopija. Priskyrimo operatorius iškviečiamas, kai jau inicijuotam objektui priskiriama nauja reikšmė iš kito esamo objekto. Aukščiau pateiktame pavyzdyje (1) iškviečia kopijavimo konstruktorių ir (2) – priskyrimo operatorių. Daugiau informacijos rasite čia.

Pavyzdys – klasė, kur reikalingas kopijavimo konstruktorius

Toliau pateikiama visa C++ programa, demonstruojanti Copy konstruktoriaus naudojimą. Šioje eilutėje klasėje turime parašyti kopijavimo konstruktorių.

Pavyzdys:

C++




// 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;> }>

>

Išvestis

GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>

Kokia būtų problema, jei pašalintume kopijavimo konstruktorių iš aukščiau pateikto kodo?

Jei pašalinsime kopijavimo konstruktorių iš aukščiau pateiktos programos, negausime laukiamos išvesties. Str2 pakeitimai taip pat atsispindi str1, ko niekada nesitikima.

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;> }>

>

>

Išvestis:

GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>

Ar galime padaryti kopijavimo konstruktorių privatų?

taip, kopijavimo konstruktorius gali būti privatus. Kai klasėje kopijavimo konstruktorių padarome privatų, tos klasės objektai tampa nebekopijuojami. Tai ypač naudinga, kai mūsų klasėje yra nuorodų arba dinamiškai paskirstytų išteklių. Tokiose situacijose galime parašyti savo kopijų konstruktorių, kaip nurodyta aukščiau pateiktame eilutės pavyzdyje, arba sukurti privačios kopijos konstruktorių, kad naudotojai vykdymo metu gautų kompiliatoriaus klaidų, o ne netikėtumų.

Kodėl argumentas kopijavimo konstruktoriui turi būti perduodamas kaip nuoroda?

Kopijos konstruktorius iškviečiamas, kai objektas perduodamas pagal vertę. Pats kopijavimo konstruktorius yra funkcija. Taigi, jei kopijavimo konstruktoriuje perduodame argumentą pagal vertę, bus iškviestas kopijavimo konstruktorius, kuris iškviestų kopijavimo konstruktorių, kuris tampa nesibaigiančia iškvietimų grandine. Todėl kompiliatorius neleidžia parametrų perduoti pagal vertę.

Kodėl argumentas kopijavimo konstruktoriui turėtų būti const?

Viena iš praėjimo priežasčių konst nuoroda yra ta, kurią turėtume naudoti konst C++, kur įmanoma, kad objektai nebūtų atsitiktinai modifikuoti. Tai viena gera priežastis perduoti nuorodą kaip konst , bet čia yra daugiau nei „ Kodėl argumentas kopijavimo konstruktoriui turėtų būti const?