Predpogoj: Konstruktor v C++
A konstruktor kopiranja je funkcija članica, ki inicializira objekt z uporabo drugega objekta istega razreda. Preprosto povedano, konstruktor, ki ustvari objekt tako, da ga inicializira z objektom istega razreda, ki je bil ustvarjen prej, je znan kot konstruktor kopiranja .
Konstruktor kopiranja se uporablja za inicializacijo članov novo ustvarjenega objekta s kopiranjem članov že obstoječega objekta.
Konstruktor kot argument vzame sklic na objekt istega razreda.
Sample(Sample &t) { id=t.id; }>
Postopek inicializacije članov objekta prek konstruktorja kopiranja je znan kot inicializacija kopiranja.
Imenuje se tudi inicializacija po članih, ker konstruktor kopiranja inicializira en objekt z obstoječim objektom, pri čemer oba pripadata istemu razredu na osnovi kopiranja člana za članom.
Programer lahko eksplicitno definira konstruktor kopiranja. Če programer ne definira konstruktorja kopiranja, to namesto nas naredi prevajalnik.
primer:
kaj pomeni xdxd

Sintaksa konstruktorja kopiranja
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;> }> |
>
>Izhod
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;> }> |
>
>Izhod
1001 Manjeet 10000 1001 Manjeet>
Značilnosti Copy Constructorja
1. Konstruktor kopiranja se uporablja za inicializacijo članov novo ustvarjenega objekta s kopiranjem članov že obstoječega objekta.
2. Konstruktor kot argument vzame sklic na objekt istega razreda. Če posredujete predmet po vrednosti v konstruktorju kopiranja, bi to povzročilo rekurziven klic k samemu konstruktorju kopiranja. To se zgodi, ker posredovanje vrednosti vključuje izdelavo kopije, izdelava kopije pa vključuje klicanje konstruktorja kopiranja, kar vodi do neskončne zanke. Uporaba sklica se izogne tej rekurziji. Zato uporabljamo referenco objektov, da se izognemo neskončnim klicem.
Sample(Sample &t) { id=t.id; }>
3. Postopek inicializacije članov objekta prek konstruktorja kopiranja je znan kot inicializacija kopiranja.
4 . Imenuje se tudi inicializacija po članih, ker konstruktor kopiranja inicializira en objekt z obstoječim objektom, pri čemer oba pripadata istemu razredu na osnovi kopiranja za vsakega člana.
5. Programer lahko eksplicitno definira konstruktor kopiranja. Če programer ne definira konstruktorja kopiranja, to namesto nas naredi prevajalnik.
primer:
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;> }> |
>
>Izhod
p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>
Vrste konstruktorjev kopiranja
1. Privzeti konstruktor kopiranja
Implicitno definiran konstruktor kopiranja bo kopiral osnove in člane objekta v istem vrstnem redu, v katerem bi konstruktor inicializiral baze in člane objekta.
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;> }> |
>
>Izhod
ID=10 ID=10>
2. Konstruktor uporabniško definiranega kopiranja
Uporabniško definiran konstruktor kopiranja je na splošno potreben, kadar ima objekt v lasti kazalce ali reference, ki jih ni mogoče deliti, na primer na datoteko; v tem primeru je treba napisati tudi destruktor in operator dodelitve
C++
str.replace v Javi
// 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;> }> |
>
>Izhod
ID=10 ID=10>
C++
zasebna proti javni 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;> }> |
>
>Izhod
1001 Ram 10000 1001 Ram 10000>
Kdaj se pokliče konstruktor kopiranja?
V C++ lahko konstruktorja kopiranja pokličete v naslednjih primerih:
- Ko je predmet razreda vrnjen po vrednosti.
- Ko je predmet razreda posredovan (v funkcijo) po vrednosti kot argument.
- Ko je objekt zgrajen na podlagi drugega predmeta istega razreda.
- Ko prevajalnik ustvari začasni objekt.
Ni pa zagotovljeno, da bo v vseh teh primerih poklican konstruktor kopije, ker standard C++ omogoča prevajalniku, da v določenih primerih optimizira kopijo, en primer je optimizacija povratne vrednosti (včasih imenovan tudi RVO).
Kopiraj Elision
Pri izločitvi kopiranja prevajalnik prepreči izdelavo dodatnih kopij, kar prihrani prostor in izboljša kompleksnost programa (tako časa kot prostora); Zato je koda bolj optimizirana.
primer:
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;> }> |
>
>Izhod
GFG! GFG! GFG!>
Zdaj se mora prevajalnik odločiti, kaj želi natisniti, lahko natisne zgornji izhod ali natisne primer 1 ali primer 2 spodaj, in to je tisto Optimizacija povratne vrednosti je. Preprosto povedano, RVO je tehnika, ki daje prevajalniku nekaj dodatne moči za prekinitev ustvarjenega začasnega objekta, kar ima za posledico spremembo opazovanega obnašanja/značilnosti končnega programa.
1. primer:
GFG! GFG!>
2. primer:
GFG!>
Kdaj je potreben uporabniško definiran konstruktor kopiranja?
Če ne definiramo lastnega konstruktorja kopiranja, prevajalnik C++ ustvari privzeti konstruktor kopiranja za vsak razred, ki izvaja kopiranje med objekti po članih. Konstruktor kopij, ki ga ustvari prevajalnik, na splošno dobro deluje. Lasten konstruktor kopiranja moramo definirati le, če ima objekt kazalce ali kakršno koli dodelitev vira med izvajanjem, npr. ročaj datoteke , omrežno povezavo itd.
Privzeto konstruktor naredi samo plitvo kopiranje.
java system.out.println
Globoko kopiranje je možno le z uporabniško definiranim konstruktorjem kopiranja. V uporabniško definiranem konstruktorju kopiranja poskrbimo, da kazalci (ali reference) kopiranih objektov kažejo na nove pomnilniške lokacije.
Konstruktor v primerjavi z operatorjem dodelitve
Glavna razlika med konstruktorjem kopiranja in operaterjem dodelitve je v tem, da konstruktor kopiranja naredi novo shrambo pomnilnika vsakič, ko je poklican, medtem ko operater dodelitve ne naredi nove shrambe pomnilnika.
Kateri od naslednjih dveh stavkov kliče konstruktor kopiranja in kateri operater dodelitve?
MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = t1; // -----> (2)>
Konstruktor kopije se pokliče, ko se iz obstoječega predmeta ustvari nov objekt kot kopija obstoječega objekta. Operator dodelitve se pokliče, ko je že inicializiranemu objektu dodeljena nova vrednost iz drugega obstoječega objekta. V zgornjem primeru (1) pokliče konstruktor kopiranja in (2) pokliče operator dodelitve. Glejte to za več podrobnosti.
Primer – razred, kjer je potreben konstruktor kopiranja
Sledi celoten program C++ za predstavitev uporabe konstruktorja kopiranja. V naslednjem razredu String moramo napisati konstruktor kopiranja.
primer:
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;> }> |
>
>Izhod
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>
Kakšna bi bila težava, če odstranimo konstruktor kopiranja iz zgornje kode?
Če iz zgornjega programa odstranimo konstruktor kopiranja, ne dobimo pričakovanega rezultata. Spremembe str2 se odražajo tudi v str1, kar ni nikoli pričakovano.
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;> }> |
>
>
Izhod:
GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>
Ali lahko naredimo konstruktor kopiranja zasebni?
da konstruktor kopij lahko naredite zasebnega. Ko v razredu naredimo konstruktor kopiranja zaseben, predmetov tega razreda ni mogoče kopirati. To je še posebej uporabno, če ima naš razred kazalce ali dinamično dodeljene vire. V takšnih situacijah lahko napišemo lasten konstruktor kopij, kot je zgornji primer niza, ali naredimo zasebni konstruktor kopij, tako da uporabniki med izvajanjem dobijo napake prevajalnika namesto presenečenj.
Zakaj je treba argument konstruktorju kopiranja posredovati kot referenco?
Ko je predmet posredovan z vrednostjo, se pokliče konstruktor kopiranja. Konstruktor sam po sebi je funkcija. Torej, če posredujemo argument po vrednosti v konstruktorju kopiranja, bi bil izveden klic konstruktorju kopiranja za klic konstruktorja kopiranja, ki postane neprekinjena veriga klicev. Zato prevajalnik ne dovoljuje posredovanja parametrov po vrednosti.
Zakaj mora biti argument za konstruktor kopiranja const?
En razlog za prehod konst referenca je, ki bi jo morali uporabiti konst v C++, kjer koli je to mogoče, tako da objekti niso pomotoma spremenjeni. To je dober razlog za posredovanje sklica kot konst , vendar je več kot ' Zakaj mora biti argument za konstruktor kopiranja const?'