logo

Kopieer Constructor in C++

Voorwaarde: Constructeur in C++

A kopieer constructor is een lidfunctie die een object initialiseert met behulp van een ander object van dezelfde klasse. In eenvoudige bewoordingen staat een constructor die een object creëert door het te initialiseren met een object van dezelfde klasse, dat eerder is gemaakt, bekend als een kopieer constructor .



De Copy-constructor wordt gebruikt om de leden van een nieuw gemaakt object te initialiseren door de leden van een reeds bestaand object te kopiëren.

De Copy-constructor neemt een verwijzing naar een object van dezelfde klasse als argument.

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

Het proces van het initialiseren van leden van een object via een kopieconstructor staat bekend als kopieerinitialisatie.



Het wordt ook wel lidgewijze initialisatie genoemd omdat de kopieconstructor één object initialiseert met het bestaande object, die beide tot dezelfde klasse behoren, op basis van lid-voor-lid-kopie.

De kopieerconstructor kan expliciet door de programmeur worden gedefinieerd. Als de programmeur de kopieconstructor niet definieert, doet de compiler dat voor ons.

Voorbeeld:



Oracle SQL is niet gelijk
Syntaxis van Copy Constructor met voorbeeld

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

>

>

Uitvoer

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

>

>

Uitvoer

 1001 Manjeet 10000 1001 Manjeet>

Kenmerken van Copy Constructor

1. De kopieerconstructor wordt gebruikt om de leden van een nieuw gemaakt object te initialiseren door de leden van een reeds bestaand object te kopiëren.

2. De Copy-constructor neemt een verwijzing naar een object van dezelfde klasse als argument. Als u het object op waarde doorgeeft in de kopieerconstructor, resulteert dit in een recursieve aanroep naar de kopieerconstructor zelf. Dit gebeurt omdat het doorgeven van de waarde het maken van een kopie inhoudt, en het maken van een kopie het aanroepen van de kopieerconstructor inhoudt, wat leidt tot een oneindige lus. Door gebruik te maken van een referentie wordt deze recursie vermeden. We gebruiken dus referentie van objecten om oneindige oproepen te voorkomen.

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

3. Het proces van het initialiseren van leden van een object via een kopieerconstructor staat bekend als kopieer initialisatie.

4 . Het wordt ook lidgewijze initialisatie genoemd omdat de kopieconstructor één object initialiseert met het bestaande object, die beide tot dezelfde klasse behoren, op basis van lid-voor-lid-kopie.

5. De kopieerconstructor kan expliciet door de programmeur worden gedefinieerd. Als de programmeur de kopieconstructor niet definieert, doet de compiler dat voor ons.

Voorbeeld:

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

>

>

een shellscript uitvoerbaar maken
Uitvoer

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

Soorten kopieerconstructeurs

1. Standaardkopieconstructor

Een impliciet gedefinieerde kopieerconstructor kopieert de bases en leden van een object in dezelfde volgorde waarin een constructor de bases en leden van het object zou initialiseren.

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

>

>

Uitvoer

 ID=10 ID=10>

2. Door de gebruiker gedefinieerde kopieerconstructor

Een door de gebruiker gedefinieerde kopieerconstructor is over het algemeen nodig wanneer een object pointers of niet-deelbare verwijzingen bezit, zoals naar een bestand, in welk geval ook een destructor en een toewijzingsoperator moeten worden geschreven

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

>

>

Uitvoer

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

>

>

Uitvoer

 1001 Ram 10000 1001 Ram 10000>

Wanneer wordt de kopieerconstructor aangeroepen?

In C++ kan in de volgende gevallen een Copy Constructor worden aangeroepen:

  • Wanneer een object van de klasse op waarde wordt geretourneerd.
  • Wanneer een object van de klasse door waarde als argument wordt doorgegeven (aan een functie).
  • Wanneer een object wordt geconstrueerd op basis van een ander object van dezelfde klasse.
  • Wanneer de compiler een tijdelijk object genereert.

Het is echter niet gegarandeerd dat in al deze gevallen een kopieerconstructor wordt aangeroepen, omdat de C++-standaard de compiler in bepaalde gevallen toestaat de kopie te optimaliseren. Een voorbeeld is de optimalisatie van de retourwaarde (ook wel RVO genoemd).

Kopieer Elision

Bij copy elision voorkomt de compiler het maken van extra kopieën, wat resulteert in ruimtebesparing en een betere programmacomplexiteit (zowel tijd als ruimte); Daarom wordt de code geoptimaliseerd.

Voorbeeld:

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

>

>

Uitvoer

 GFG! GFG! GFG!>

Nu is het aan de compiler om te beslissen wat hij wil afdrukken, hij kan de bovenstaande uitvoer afdrukken of case 1 of case 2 hieronder afdrukken, en dit is wat Optimalisatie van de retourwaarde is. In eenvoudige woorden, RVO is een techniek die de compiler wat extra kracht geeft om het gemaakte tijdelijke object te beëindigen, wat resulteert in het veranderen van het waarneembare gedrag/de kenmerken van het uiteindelijke programma.

Zaak 1:

if else-verklaring java
GFG! GFG!>

Geval 2:

GFG!>

Wanneer is een door de gebruiker gedefinieerde kopieerconstructor nodig?

Als we onze eigen kopieerconstructor niet definiëren, maakt de C++-compiler een standaardkopieconstructor voor elke klasse, die een ledengewijze kopie tussen objecten uitvoert. De door de compiler gemaakte kopieerconstructor werkt over het algemeen prima. We hoeven onze eigen kopieerconstructor alleen te definiëren als een object pointers heeft of een runtime-toewijzing van de bron, zoals een dossierhandvat , een netwerkverbinding, enz.

De standaard constructor kopieert alleen oppervlakkig.

ondiepe kopie in C++

Diep kopiëren is alleen mogelijk met een door de gebruiker gedefinieerde kopieerconstructor. In een door de gebruiker gedefinieerde kopieerconstructor zorgen we ervoor dat pointers (of verwijzingen) van gekopieerde objecten naar nieuwe geheugenlocaties verwijzen.

Diepe kopie in C++

Kopieer constructor versus toewijzingsoperator

Het belangrijkste verschil tussen Copy Constructor en Assignment Operator is dat de Copy constructor elke keer dat deze wordt aangeroepen een nieuwe geheugenopslag maakt, terwijl de toewijzingsoperator geen nieuwe geheugenopslag maakt.

Welke van de volgende twee instructies roept de kopieerconstructor aan en welke roept de toewijzingsoperator aan?

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

Een kopieconstructor wordt aangeroepen wanneer een nieuw object wordt gemaakt op basis van een bestaand object, als kopie van het bestaande object. De toewijzingsoperator wordt aangeroepen wanneer aan een reeds geïnitialiseerd object een nieuwe waarde wordt toegewezen van een ander bestaand object. In het bovenstaande voorbeeld roept (1) de kopieerconstructor aan en (2) roept de toewijzingsoperator aan. Zie dit voor meer details.

Voorbeeld – Klasse waarbij een Copy Constructor vereist is

Hieronder volgt een compleet C++-programma om het gebruik van de Copy-constructor te demonstreren. In de volgende klasse String moeten we een kopieconstructor schrijven.

Voorbeeld:

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

>

>

Uitvoer

Python tupel gesorteerd
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>

Wat zou het probleem zijn als we de kopieerconstructor uit de bovenstaande code verwijderen?

Als we de kopieerconstructor uit het bovenstaande programma verwijderen, krijgen we niet de verwachte uitvoer. De wijzigingen die in str2 zijn aangebracht, worden ook weerspiegeld in str1, wat nooit wordt verwacht.

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

>

>

Uitgang:

GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>

Kunnen we de kopieerconstructor privé maken?

Ja, een kopieconstructor kan privé worden gemaakt. Wanneer we een kopieconstructor privé maken in een klasse, worden objecten van die klasse niet-kopieerbaar. Dit is vooral handig als onze klasse pointers of dynamisch toegewezen bronnen heeft. In dergelijke situaties kunnen we onze eigen kopieerconstructor schrijven, zoals in het bovenstaande String-voorbeeld, of een privékopieconstructor maken, zodat gebruikers compilerfouten krijgen in plaats van verrassingen tijdens runtime.

Waarom moet een argument aan een kopieconstructor als referentie worden doorgegeven?

Een kopieconstructor wordt aangeroepen wanneer een object op waarde wordt doorgegeven. Kopieerconstructor zelf is een functie. Dus als we een argument op waarde doorgeven in een kopieconstructor, zou er een aanroep naar de kopieconstructor worden gedaan om de kopieconstructor aan te roepen, wat een niet-beëindigende keten van oproepen wordt. Daarom staat de compiler niet toe dat parameters op waarde worden doorgegeven.

Waarom zou het argument voor een kopieerconstructor const moeten zijn?

Eén reden om te passeren const referentie is, die we moeten gebruiken const in C++ waar mogelijk, zodat objecten niet per ongeluk worden gewijzigd. Dit is een goede reden om de verwijzing door te geven als const , maar er is meer aan de hand dan ‘ Waarom zou een argument voor een kopieerconstructor const moeten zijn?’