Forudsætning: Konstruktør i C++
EN kopi konstruktør er en medlemsfunktion, der initialiserer et objekt ved hjælp af et andet objekt af samme klasse. Enkelt sagt er en konstruktør, der skaber et objekt ved at initialisere det med et objekt af samme klasse, som er blevet oprettet tidligere, kendt som en kopi konstruktør .
Kopikonstruktør bruges til at initialisere medlemmerne af et nyoprettet objekt ved at kopiere medlemmerne af et allerede eksisterende objekt.
Copy constructor tager en reference til et objekt af samme klasse som et argument.
Sample(Sample &t) { id=t.id; }> Processen med at initialisere medlemmer af et objekt gennem en kopikonstruktør er kendt som kopiinitialisering.
Det kaldes også medlemsvis initialisering, fordi kopikonstruktøren initialiserer et objekt med det eksisterende objekt, som begge tilhører den samme klasse på et medlem for medlem kopi-basis.
Kopikonstruktøren kan defineres eksplicit af programmøren. Hvis programmøren ikke definerer kopikonstruktøren, gør compileren det for os.
Eksempel:
apache

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;> }> |
>
>Produktion
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;> }> |
>
>Produktion
1001 Manjeet 10000 1001 Manjeet>
Karakteristika for Copy Constructor
1. Kopikonstruktøren bruges til at initialisere medlemmerne af et nyoprettet objekt ved at kopiere medlemmerne af et allerede eksisterende objekt.
2. Copy constructor tager en reference til et objekt af samme klasse som et argument. Hvis du sender objektet efter værdi i kopikonstruktøren, vil det resultere i et rekursivt kald til selve kopikonstruktøren. Dette sker, fordi overførsel af værdi involverer at lave en kopi, og at lave en kopi involverer at kalde kopikonstruktøren, hvilket fører til en uendelig løkke. Ved at bruge en reference undgås denne rekursion. Så vi bruger reference til objekter for at undgå uendelige opkald.
Sample(Sample &t) { id=t.id; }> 3. Processen med at initialisere medlemmer af et objekt gennem en kopikonstruktør er kendt som kopiinitialisering.
4 . Det kaldes også medlemsvis initialisering, fordi kopikonstruktøren initialiserer et objekt med det eksisterende objekt, som begge tilhører den samme klasse på en medlem-for-medlem kopibasis.
5. Kopikonstruktøren kan defineres eksplicit af programmøren. Hvis programmøren ikke definerer kopikonstruktøren, gør compileren det for os.
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;> }> |
>
>Produktion
p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>
Typer af kopikonstruktører
1. Standard kopikonstruktør
En implicit defineret kopikonstruktør vil kopiere baserne og medlemmerne af et objekt i samme rækkefølge, som en konstruktør vil initialisere baserne og medlemmerne af 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;> }> |
>
>Produktion
ID=10 ID=10>
2. Brugerdefineret kopikonstruktør
En brugerdefineret kopikonstruktør er generelt nødvendig, når et objekt ejer pointere eller ikke-delbare referencer, såsom til en fil, i hvilket tilfælde en destructor og en tildelingsoperator også skal skrives
C++
liste node 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;> }> |
>
>Produktion
ID=10 ID=10>
C++
java-sammenkædede strenge
// 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;> }> |
>
>Produktion
1001 Ram 10000 1001 Ram 10000>
Hvornår kaldes kopikonstruktøren?
I C++ kan en Copy Constructor kaldes i følgende tilfælde:
- Når et objekt i klassen returneres af værdi.
- Når et objekt i klassen sendes (til en funktion) efter værdi som et argument.
- Når et objekt er konstrueret baseret på et andet objekt af samme klasse.
- Når compileren genererer et midlertidigt objekt.
Det er dog ikke garanteret, at en kopikonstruktør vil blive kaldt i alle disse tilfælde, fordi C++-standarden tillader compileren at optimere kopien væk i visse tilfælde, et eksempel er optimering af afkastværdi (nogle gange omtalt som RVO).
Kopier Elision
I copy elision forhindrer compileren fremstilling af ekstra kopier, hvilket resulterer i at spare plads og forbedre programmets kompleksitet (både tid og rum); Derfor gør koden mere optimeret.
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;> }> |
>
>Produktion
GFG! GFG! GFG!>
Nu er det op til compileren at beslutte, hvad den vil udskrive, den kan enten udskrive ovenstående output, eller den kan udskrive case 1 eller case 2 nedenfor, og dette er hvad Optimering af returværdi er. Med enkle ord, RVO er en teknik, der giver compileren noget ekstra kraft til at afslutte det midlertidige objekt, der er oprettet, hvilket resulterer i at ændre den observerbare adfærd/karakteristika for det endelige program.
Case 1:
GFG! GFG!>
Tilfælde 2:
GFG!>
Hvornår er der brug for en brugerdefineret kopikonstruktør?
Hvis vi ikke definerer vores egen kopikonstruktør, opretter C++-kompileren en standardkopikonstruktør for hver klasse, som laver en medlemsmæssig kopi mellem objekter. Den compiler-oprettede kopi konstruktør fungerer fint generelt. Vi skal kun definere vores egen kopikonstruktør, hvis et objekt har pointere eller en runtime allokering af ressourcen som f.eks. et filhåndtag , en netværksforbindelse osv.
Standarden konstruktør laver kun overfladisk kopi.

dynamisk array i java
Dyb kopiering er kun mulig med en brugerdefineret kopikonstruktør. I en brugerdefineret kopikonstruktør sørger vi for, at pointere (eller referencer) af kopierede objekter peger på nye hukommelsesplaceringer.
Kopikonstruktør vs Opgaveoperatør
Hovedforskellen mellem Copy Constructor og Assignment Operator er, at Copy-konstruktøren laver et nyt hukommelseslager hver gang det kaldes, mens opgaveoperatøren ikke laver nyt hukommelseslager.
Hvilken af følgende to udsagn kalder kopikonstruktøren, og hvilken kalder opgaveoperatøren?
MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = t1; // -----> (2)>
En kopikonstruktør kaldes, når et nyt objekt oprettes fra et eksisterende objekt, som en kopi af det eksisterende objekt. Tildelingsoperatoren kaldes, når et allerede initialiseret objekt tildeles en ny værdi fra et andet eksisterende objekt. I ovenstående eksempel kalder (1) kopikonstruktøren og (2) kalder tildelingsoperatøren. Se dette for flere detaljer.
Eksempel – Klasse, hvor en kopikonstruktør er påkrævet
Følgende er et komplet C++-program til at demonstrere brugen af Copy-konstruktøren. I den følgende String-klasse skal 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;> }> |
>
>Produktion
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>
Hvad ville være problemet, hvis vi fjerner kopikonstruktøren fra ovenstående kode?
Hvis vi fjerner kopikonstruktøren fra ovenstående program, får vi ikke det forventede output. Ændringerne i str2 afspejler sig også i str1, hvilket aldrig forventes.
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;> }> |
>
>
Produktion:
GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>
Kan vi gøre kopikonstruktøren privat?
Ja, en kopikonstruktør kan gøres privat. Når vi gør en kopikonstruktør privat i en klasse, bliver objekter i den klasse ikke-kopierbare. Dette er især nyttigt, når vores klasse har pointere eller dynamisk allokerede ressourcer. I sådanne situationer kan vi enten skrive vores egen kopikonstruktør som ovenstående String-eksempel eller lave en privat kopikonstruktør, så brugerne får kompileringsfejl frem for overraskelser under kørsel.
Hvorfor skal et argument til en kopikonstruktør sendes som reference?
En kopikonstruktør kaldes, når et objekt sendes af værdi. Copy constructor er i sig selv en funktion. Så hvis vi sender et argument efter værdi i en kopikonstruktør, vil der blive foretaget et kald til kopikonstruktøren for at kalde kopikonstruktøren, som bliver en ikke-afsluttende kæde af kald. Derfor tillader compiler ikke, at parametre overføres efter værdi.
Hvorfor skal argumentet til en kopikonstruktør være const?
En grund til at bestå konst reference er, at vi skal bruge konst i C++ hvor det er muligt, så objekter ikke ved et uheld ændres. Dette er en god grund til at videregive reference som konst , men der er mere i det end ' Hvorfor skulle argumentet til en kopikonstruktør være const?'