logo

Kopier Constructor i C++

Forutsetning: Konstruktør i C++

EN kopi konstruktør er en medlemsfunksjon som initialiserer et objekt ved å bruke et annet objekt av samme klasse. Enkelt sagt, en konstruktør som lager et objekt ved å initialisere det med et objekt av samme klasse, som har blitt opprettet tidligere, er kjent som en kopi konstruktør .



Kopikonstruktør brukes til å initialisere medlemmene til et nyopprettet objekt ved å kopiere medlemmene til et allerede eksisterende objekt.

Copy constructor tar en referanse til et objekt av samme klasse som et argument.

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

Prosessen med å initialisere medlemmer av et objekt gjennom en kopikonstruktør er kjent som kopiinitialisering.



Det kalles også medlemsvis initialisering fordi kopikonstruktøren initialiserer ett objekt med det eksisterende objektet, som begge tilhører samme klasse på en kopibasis for medlem for medlem.

Kopikonstruktøren kan defineres eksplisitt av programmereren. Hvis programmereren ikke definerer kopikonstruktøren, gjør kompilatoren det for oss.

Eksempel:



hva er autowired i java
Syntaks for Copy Constructor med eksempel

Syntaks for Copy Constructor

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

>

>

Produksjon

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

>

>

Produksjon

 1001 Manjeet 10000 1001 Manjeet>

Kjennetegn ved Copy Constructor

1. Kopikonstruktøren brukes til å initialisere medlemmene til et nyopprettet objekt ved å kopiere medlemmene til et allerede eksisterende objekt.

2. Copy constructor tar en referanse til et objekt av samme klasse som et argument. Hvis du sender objektet etter verdi i kopikonstruktøren, vil det resultere i et rekursivt kall til selve kopikonstruktøren. Dette skjer fordi å gå forbi verdi innebærer å lage en kopi, og å lage en kopi innebærer å kalle kopikonstruktøren, noe som fører til en uendelig løkke. Ved å bruke en referanse unngår du denne rekursjonen. Så vi bruker referanse til objekter for å unngå uendelige anrop.

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

3. Prosessen med å initialisere medlemmer av et objekt gjennom en kopikonstruktør er kjent som kopiinitialisering.

4 . Det kalles også medlemsvis initialisering fordi kopikonstruktøren initialiserer ett objekt med det eksisterende objektet, som begge tilhører samme klasse på en kopi-basis for medlem.

5. Kopikonstruktøren kan defineres eksplisitt av programmereren. Hvis programmereren ikke definerer kopikonstruktøren, gjør kompilatoren det for oss.

Eksempel:

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

>

>

Produksjon

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

Typer kopikonstruktører

1. Standard kopikonstruktør

En implisitt definert kopikonstruktør vil kopiere basene og medlemmene til et objekt i samme rekkefølge som en konstruktør vil initialisere basene og medlemmene til objektet.

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

>

>

Produksjon

 ID=10 ID=10>

2. Brukerdefinert kopikonstruktør

En brukerdefinert kopikonstruktør er vanligvis nødvendig når et objekt eier pekere eller ikke-delbare referanser, for eksempel til en fil, i så fall bør en destruktor og en tilordningsoperatør også skrives

C++


listenode i java



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

>

>

Produksjon

 ID=10 ID=10>

C++


alfabetet av tall



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

>

>

Produksjon

 1001 Ram 10000 1001 Ram 10000>

Når kalles kopikonstruktøren?

I C++ kan en kopikonstruktør kalles i følgende tilfeller:

  • Når et objekt i klassen returneres av verdi.
  • Når et objekt i klassen sendes (til en funksjon) med verdi som et argument.
  • Når et objekt er konstruert basert på et annet objekt av samme klasse.
  • Når kompilatoren genererer et midlertidig objekt.

Det er imidlertid ikke garantert at en kopikonstruktør vil bli kalt i alle disse tilfellene, fordi C++-standarden lar kompilatoren optimalisere kopien bort i visse tilfeller, et eksempel er avkastningsverdioptimalisering (noen ganger referert til som RVO).

Kopier Elision

I copy elision forhindrer kompilatoren å lage ekstra kopier som resulterer i å spare plass og bedre programkompleksiteten (både tid og plass); Derfor gjør koden mer optimalisert.

Eksempel:

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

>

>

Produksjon

 GFG! GFG! GFG!>

Nå er det opp til kompilatoren å bestemme hva den vil skrive ut, den kan enten skrive ut utdataene ovenfor eller den kan skrive ut case 1 eller case 2 nedenfor, og dette er hva Optimalisering av returverdi er. Med enkle ord, RVO er en teknikk som gir kompilatoren litt ekstra kraft til å avslutte det midlertidige objektet som er opprettet, noe som resulterer i å endre den observerbare oppførselen/karakteristikkene til det endelige programmet.

Tilfelle 1:

GFG! GFG!>

Tilfelle 2:

GFG!>

Når trengs en brukerdefinert kopikonstruktør?

Hvis vi ikke definerer vår egen kopikonstruktør, oppretter C++-kompilatoren en standard kopikonstruktør for hver klasse som gjør en medlemsmessig kopi mellom objekter. Den kompilator-opprettede kopi-konstruktøren fungerer fint generelt. Vi trenger å definere vår egen kopi-konstruktør bare hvis et objekt har pekere eller en kjøretidsallokering av ressursen som et filhåndtak , en nettverkstilkobling osv.

Standaren konstruktør gjør bare grunne kopier.

grunt eksemplar i C++

dynamisk array i java

Dypkopiering er kun mulig med en brukerdefinert kopikonstruktør. I en brukerdefinert kopikonstruktør sørger vi for at pekere (eller referanser) til kopierte objekter peker til nye minneplasseringer.

Deep Copy i C++

Kopier konstruktør vs tildelingsoperatør

Hovedforskjellen mellom Copy Constructor og Assignment Operator er at Copy-konstruktøren lager en ny minnelagring hver gang den kalles, mens tildelingsoperatøren ikke lager ny minnelagring.

Hvilken av følgende to utsagn kaller kopikonstruktøren og hvilken kaller oppdragsoperatøren?

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

En kopikonstruktør kalles når et nytt objekt opprettes fra et eksisterende objekt, som en kopi av det eksisterende objektet. Tilordningsoperatoren kalles når et allerede initialisert objekt blir tildelt en ny verdi fra et annet eksisterende objekt. I eksemplet ovenfor kaller (1) kopikonstruktøren og (2) kaller oppdragsoperatøren. Se denne for flere detaljer.

Eksempel – Klasse hvor en kopikonstruktør er påkrevd

Følgende er et komplett C++-program for å demonstrere bruken av Copy-konstruktøren. I den følgende strengklassen må vi skrive en kopikonstruktør.

Eksempel:

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

>

>

Produksjon

GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>

Hva ville være problemet hvis vi fjerner kopikonstruktøren fra koden ovenfor?

Hvis vi fjerner kopikonstruktøren fra programmet ovenfor, får vi ikke det forventede resultatet. Endringene som er gjort i str2 gjenspeiler også i str1 som aldri er forventet.

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

>

>

Produksjon:

GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>

Kan vi gjøre kopikonstruktøren privat?

Ja, en kopikonstruktør kan gjøres privat. Når vi gjør en kopikonstruktør privat i en klasse, blir objekter i den klassen ikke-kopierbare. Dette er spesielt nyttig når klassen vår har pekere eller dynamisk tildelte ressurser. I slike situasjoner kan vi enten skrive vår egen kopikonstruktør som ovenfor String-eksempel eller lage en privat kopikonstruktør slik at brukere får kompilatorfeil i stedet for overraskelser under kjøring.

Hvorfor må argumentet til en kopikonstruktør sendes som referanse?

En kopikonstruktør kalles når et objekt sendes med verdi. Selve kopikonstruktøren er en funksjon. Så hvis vi sender et argument etter verdi i en kopikonstruktør, vil et kall til kopikonstruktøren bli gjort for å kalle kopikonstruktøren som blir en ikke-avsluttende kjede av samtaler. Derfor tillater ikke kompilatoren at parametere sendes etter verdi.

Hvorfor skal argumentet til en kopikonstruktør være const?

En grunn til å bestå konst referanse er at vi bør bruke konst i C++ der det er mulig, slik at objekter ikke endres ved et uhell. Dette er en god grunn til å bestå referanse som konst , men det er mer til det enn ' Hvorfor skal argumentet til en kopikonstruktør være const?’