Predpoklad: Konštruktor v C++
A kopírovať konštruktor je členská funkcia, ktorá inicializuje objekt pomocou iného objektu rovnakej triedy. Jednoducho povedané, konštruktor, ktorý vytvára objekt jeho inicializáciou s objektom rovnakej triedy, ktorý bol vytvorený predtým, je známy ako kopírovať konštruktor .
Konštruktor kopírovania sa používa na inicializáciu členov novovytvoreného objektu skopírovaním členov už existujúceho objektu.
Konštruktor kopírovania berie ako argument odkaz na objekt rovnakej triedy.
Sample(Sample &t) { id=t.id; }>
Proces inicializácie členov objektu prostredníctvom konštruktora kópie je známy ako inicializácia kópie.
Nazýva sa to aj inicializácia po členoch, pretože konštruktor kópie inicializuje jeden objekt s existujúcim objektom, pričom oba patria do rovnakej triedy na základe kópie člena po člene.
Kopírovací konštruktor môže byť definovaný explicitne programátorom. Ak programátor nedefinuje konštruktor kopírovania, urobí to za nás kompilátor.
Príklad:
poštár

Syntax 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;> }> |
>
>Výkon
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;> }> |
>
>Výkon
1001 Manjeet 10000 1001 Manjeet>
Charakteristika Copy Constructor
1. Kopírovací konštruktor sa používa na inicializáciu členov novovytvoreného objektu skopírovaním členov už existujúceho objektu.
2. Konštruktor kopírovania berie ako argument odkaz na objekt rovnakej triedy. Ak odovzdáte objekt podľa hodnoty v konštruktore kópie, bude to mať za následok rekurzívne volanie samotného konštruktora kópie. Stáva sa to preto, že odovzdanie hodnoty zahŕňa vytvorenie kópie a vytvorenie kópie zahŕňa volanie konštruktora kópie, čo vedie k nekonečnej slučke. Použitím odkazu sa vyhnete tejto rekurzii. Takže používame referenciu objektov, aby sme sa vyhli nekonečným volaniam.
Sample(Sample &t) { id=t.id; }>
3. Proces inicializácie členov objektu prostredníctvom konštruktora kopírovania je známy ako inicializácia kopírovania.
4 . Nazýva sa to aj inicializácia po členoch, pretože konštruktor kópie inicializuje jeden objekt s existujúcim objektom, pričom oba patria do rovnakej triedy na základe kópií po členoch.
5. Kopírovací konštruktor môže byť definovaný explicitne programátorom. Ak programátor nedefinuje konštruktor kopírovania, urobí to za nás kompilátor.
Príklad:
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;> }> |
>
>Výkon
p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>
Typy kopírovacích konštruktérov
1. Predvolený konštruktor kópií
Implicitne definovaný konštruktor kopírovania skopíruje základy a členy objektu v rovnakom poradí, v akom by konštruktor inicializoval základy a členy objektu.
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;> }> |
prednosť java operátora
>
>Výkon
ID=10 ID=10>
2. Používateľom definovaný konštruktor kópií
Používateľom definovaný konštruktor kópie je vo všeobecnosti potrebný, keď objekt vlastní ukazovatele alebo nezdieľateľné odkazy, ako napríklad na súbor, v takom prípade by sa mal napísať aj deštruktor a operátor priradenia.
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;> }> |
>
zoraďte zoznam polí v jazyku Java
>Výkon
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;> }> |
>
>Výkon
1001 Ram 10000 1001 Ram 10000>
Kedy sa volá konštruktor kópie?
V C++ môže byť Copy Constructor zavolaný v nasledujúcich prípadoch:
- Keď je objekt triedy vrátený hodnotou.
- Keď je objekt triedy odovzdaný (funkcii) hodnotou ako argument.
- Keď je objekt skonštruovaný na základe iného objektu rovnakej triedy.
- Keď kompilátor vygeneruje dočasný objekt.
Nie je však zaručené, že vo všetkých týchto prípadoch bude zavolaný konštruktor kópie, pretože štandard C++ umožňuje kompilátoru optimalizovať kópiu v určitých prípadoch, napríklad optimalizácia návratnej hodnoty (niekedy označované ako RVO).
Kopírovať Elision
V copy elision kompilátor zabraňuje vytváraniu ďalších kópií, čo má za následok úsporu miesta a lepšiu zložitosť programu (čas aj priestor); Preto je kód viac optimalizovaný.
Príklad:
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;> }> |
>
>Výkon
GFG! GFG! GFG!>
Teraz je na kompilátore, aby sa rozhodol, čo chce vytlačiť, môže buď vytlačiť vyššie uvedený výstup, alebo môže vytlačiť prípad 1 alebo prípad 2 nižšie, a to je to, čo Optimalizácia návratnej hodnoty je. jednoduchými slovami, RVO je technika, ktorá dáva kompilátoru dodatočnú silu na ukončenie vytvoreného dočasného objektu, čo vedie k zmene pozorovateľného správania/charakteristiky konečného programu.
Prípad 1:
GFG! GFG!>
Prípad 2:
GFG!>
Kedy je potrebný užívateľom definovaný konštruktor kópií?
Ak nedefinujeme náš vlastný konštruktor kópie, kompilátor C++ vytvorí predvolený konštruktor kópie pre každú triedu, ktorý vykoná kopírovanie medzi objektmi po členoch. Konštruktor kópií vytvorený kompilátorom funguje vo všeobecnosti dobre. Náš vlastný konštruktor kópií musíme definovať iba vtedy, ak má objekt ukazovatele alebo akékoľvek pridelenie zdroja za behu rukoväť súboru , sieťové pripojenie atď.
Predvolená hodnota konštruktor robí iba plytkú kópiu.
Hlboké kopírovanie je možné len s užívateľom definovaným konštruktorom kopírovania. V užívateľsky definovanom konštruktore kópií zabezpečujeme, aby ukazovatele (alebo referencie) skopírovaných objektov smerovali na nové miesta v pamäti.
Kopírovať konštruktor vs operátor priradenia
Hlavný rozdiel medzi konštruktorom kopírovania a operátorom priradenia je v tom, že konštruktor kopírovania vytvára nové pamäťové úložisko pri každom volaní, zatiaľ čo operátor priraďovania nevytvára nové pamäťové úložisko.
Ktorý z nasledujúcich dvoch príkazov volá konštruktor kopírovania a ktorý operátor priradenia?
MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = ti; // -----> (2)>
Konštruktor kópie sa volá, keď sa vytvorí nový objekt z existujúceho objektu ako kópia existujúceho objektu. Operátor priradenia sa volá, keď je už inicializovanému objektu priradená nová hodnota z iného existujúceho objektu. Vo vyššie uvedenom príklade (1) volá konštruktor kopírovania a (2) volá operátor priradenia. Ďalšie podrobnosti nájdete v tejto časti.
Príklad – Trieda, kde sa vyžaduje konštruktor kopírovania
Nasleduje kompletný program C++ na demonštráciu použitia konštruktora Copy. V nasledujúcej triede String musíme napísať konštruktor kopírovania.
Príklad:
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;> }> |
>
>Výkon
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>
Aký by bol problém, keby sme z vyššie uvedeného kódu odstránili konštruktor kópie?
Ak odstránime konštruktor kópie z vyššie uvedeného programu, nedostaneme očakávaný výstup. Zmeny vykonané v str2 sa odrážajú aj v str1, čo sa nikdy neočakáva.
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;> }> |
vymazanie z binárneho vyhľadávacieho stromu
>
>
Výkon:
GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>
Môžeme urobiť konštruktor kópie súkromným?
Áno, konštruktor kópie môže byť nastavený ako súkromný. Keď urobíme konštruktor kópie súkromným v triede, objekty tejto triedy sa stanú nekopírovateľnými. Toto je obzvlášť užitočné, keď má naša trieda ukazovatele alebo dynamicky prideľované zdroje. V takýchto situáciách môžeme buď napísať vlastný konštruktor kópií, ako je vyššie uvedený príklad String, alebo vytvoriť konštruktor súkromnej kópie, takže používatelia dostanú chyby kompilátora namiesto prekvapení počas behu.
Prečo musí byť argument konštruktora kópie odovzdaný ako odkaz?
Konštruktor kópie sa volá, keď sa objektu odovzdáva hodnota. Samotný konštruktor kopírovania je funkcia. Ak teda v konštruktore kópie odovzdáme argument podľa hodnoty, vykoná sa volanie konštruktora kópie na zavolanie konštruktora kópie, ktorý sa stane neukončujúcim reťazcom volaní. Preto kompilátor neumožňuje odovzdávanie parametrov hodnotou.
Prečo by argument pre konštruktor kópie mal byť const?
Jeden dôvod, prečo prejsť konšt odkaz je, že by sme mali použiť konšt v C++ všade tam, kde je to možné, aby nedošlo k náhodnej úprave objektov. To je jeden z dobrých dôvodov pre odovzdanie odkazu ako konšt , ale je v tom viac ako „ Prečo by argument pre konštruktor kópie mal byť konštantný?‘