logo

Kopioi Constructor C++:ssa

Edellytys: Konstruktori C++:ssa

A kopioinnin rakentaja on jäsenfunktio, joka alustaa objektin käyttämällä toista saman luokan objektia. Yksinkertaisesti sanottuna konstruktori, joka luo objektin alustamalla sen saman luokan objektilla, joka on luotu aiemmin, tunnetaan nimellä kopioinnin rakentaja .



Kopioi konstruktoria käytetään alustamaan juuri luodun objektin jäsenet kopioimalla jo olemassa olevan objektin jäsenet.

Kopiokonstruktori ottaa viittauksen saman luokan objektiin argumenttina.

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

Prosessi, jossa objektin jäsenet alustetaan kopiokonstruktorin avulla, tunnetaan kopioiden alustuksena.



Sitä kutsutaan myös jäsenkohtaiseksi alustukseksi, koska kopiokonstruktori alustaa yhden objektin olemassa olevalla objektilla, jotka molemmat kuuluvat samaan luokkaan jäsen kerrallaan.

Ohjelmoija voi määrittää kopiokonstruktorin eksplisiittisesti. Jos ohjelmoija ei määrittele kopiokonstruktoria, kääntäjä tekee sen puolestamme.

Esimerkki:



voiko abstraktilla luokalla olla konstruktori
Copy Constructorin syntaksi esimerkin kanssa

Copy Constructorin syntaksi

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

>

>

Lähtö

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

>

>

Lähtö

 1001 Manjeet 10000 1001 Manjeet>

Copy Constructorin ominaisuudet

1. Kopiokonstruktoria käytetään alustamaan juuri luodun objektin jäsenet kopioimalla jo olemassa olevan objektin jäsenet.

2. Kopiokonstruktori ottaa viittauksen saman luokan objektiin argumenttina. Jos ohitat objektin arvon perusteella kopioiden rakentajassa, se johtaisi rekursiiviseen kutsuun itse kopion rakentajalle. Tämä tapahtuu, koska arvon ohittaminen edellyttää kopion tekemistä, ja kopion tekeminen edellyttää kopion rakentajan kutsumista, mikä johtaa äärettömään silmukkaan. Viitteen käyttäminen välttää tämän rekursion. Joten käytämme viittausta objektiin välttääksemme äärettömiä kutsuja.

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

3. Objektin jäsenten alustusprosessi kopiokonstruktorin kautta tunnetaan nimellä kopioida alustus.

4 . Sitä kutsutaan myös jäsenkohtaiseksi alustukseksi, koska kopiokonstruktori alustaa yhden objektin olemassa olevalla objektilla, jotka molemmat kuuluvat samaan luokkaan jäsenkohtaisesti.

5. Ohjelmoija voi määrittää kopiokonstruktorin eksplisiittisesti. Jos ohjelmoija ei määrittele kopiokonstruktoria, kääntäjä tekee sen puolestamme.

Esimerkki:

shweta tiwari

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

>

>

Lähtö

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

Kopiointikonstruktorien tyypit

1. Oletuskopiointikonstruktori

Implisiittisesti määritelty kopiokonstruktori kopioi objektin kantat ja jäsenet samassa järjestyksessä kuin rakentaja alustaisi objektin kantat ja jäsenet.

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

>

>

Lähtö

 ID=10 ID=10>

2. User Defined Copy Constructor

Käyttäjän määrittämää kopiokonstruktoria tarvitaan yleensä silloin, kun objekti omistaa osoittimia tai ei-jaettavia viittauksia, kuten tiedostoon, jolloin tulee kirjoittaa myös destruktori ja osoitusoperaattori.

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

>

>

Lähtö

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

javascript onclick

>

>

Lähtö

 1001 Ram 10000 1001 Ram 10000>

Milloin kopiokonstruktori kutsutaan?

C++:ssa Copy Constructor voidaan kutsua seuraavissa tapauksissa:

  • Kun luokan objekti palautetaan arvolla.
  • Kun luokan objekti välitetään (funktiolle) arvolla argumenttina.
  • Kun objekti on rakennettu toisen saman luokan objektin perusteella.
  • Kun kääntäjä luo väliaikaisen objektin.

Ei kuitenkaan ole taattua, että kopiokonstruktoria kutsutaan kaikissa näissä tapauksissa, koska C++-standardin avulla kääntäjä voi tietyissä tapauksissa optimoida kopioinnin pois, yksi esimerkki on palautusarvon optimointi (kutsutaan joskus nimellä RVO).

Kopioi Elision

Copy elisionissa kääntäjä estää ylimääräisten kopioiden tekemisen, mikä säästää tilaa ja parantaa ohjelman monimutkaisuutta (sekä aikaa että tilaa); Näin ollen koodi on optimoitu.

Esimerkki:

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

>

>

Lähtö

 GFG! GFG! GFG!>

Nyt kääntäjän on päätettävä, mitä se haluaa tulostaa, se voi tulostaa joko yllä olevan tulosteen tai se voi tulostaa tapauksen 1 tai tapauksen 2 alla, ja tämä on mitä Palautusarvon optimointi On. Yksinkertaisin sanoin, RVO on tekniikka, joka antaa kääntäjälle lisävoimaa lopettaa luodun väliaikaisen objektin, mikä muuttaa lopullisen ohjelman havaittavissa olevaa käyttäytymistä/ominaisuuksia.

Tapaus 1:

GFG! GFG!>

Tapaus 2:

GFG!>

Milloin käyttäjän määrittämää kopiokonstruktoria tarvitaan?

Jos emme määrittele omaa kopiokonstruktoriamme, C++-kääntäjä luo oletuskopiokonstruktorin jokaiselle luokalle, joka tekee jäsenkohtaisen kopion objektien välillä. Kääntäjän luoma kopiokonstruktori toimii yleisesti ottaen hyvin. Meidän on määritettävä oma kopiokonstruktorimme vain, jos objektilla on osoittimia tai resurssin ajonaikainen varaus, kuten tiedostokahva , verkkoyhteys jne.

Oletusarvo konstruktori tekee vain pinnallista kopiota.

matala kopio C++:ssa

Syväkopiointi on mahdollista vain käyttäjän määrittelemällä kopiointikonstruktorilla. Käyttäjän määrittämässä kopiokonstruktorissa varmistamme, että kopioitujen objektien osoittimet (tai viittaukset) osoittavat uusiin muistipaikkoihin.

Deep Copy C++:ssa

Kopioi rakentaja vs. tehtäväoperaattori

Suurin ero Copy Constructorin ja Assignment Operatorin välillä on se, että Copy Constructor tekee uuden muistitallennustilan joka kerta, kun sitä kutsutaan, kun taas määritysoperaattori ei tee uutta muistia.

Mikä seuraavista kahdesta lauseesta kutsuu kopiokonstruktoria ja mikä osoitusoperaattoria?

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

Kopiokonstruktori kutsutaan, kun uusi objekti luodaan olemassa olevasta objektista kopiona olemassa olevasta objektista. Osoitusoperaattoria kutsutaan, kun jo alustettu objekti saa uuden arvon toisesta olemassa olevasta objektista. Yllä olevassa esimerkissä (1) kutsuu kopioinnin rakentajaa ja (2) kutsuu osoitusoperaattoria. Katso tästä lisätietoja.

Esimerkki – Luokka, jossa vaaditaan kopiokonstruktori

Seuraavassa on täydellinen C++-ohjelma, joka osoittaa Copy-konstruktorin käytön. Seuraavassa String-luokassa meidän on kirjoitettava kopiokonstruktori.

Esimerkki:

C++

Linux run cmd




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

>

Lähtö

GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>

Mikä olisi ongelma, jos poistaisimme kopiokonstruktorin yllä olevasta koodista?

Jos poistamme kopiokonstruktorin yllä olevasta ohjelmasta, emme saa odotettua tulosta. Str2:een tehdyt muutokset heijastavat myös str1:ssä, mitä ei koskaan odoteta.

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

>

>

Lähtö:

GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>

Voimmeko tehdä kopiokonstruktorista yksityisen?

Joo, kopiokonstruktorista voidaan tehdä yksityinen. Kun teemme kopiokonstruktorista yksityisen luokassa, kyseisen luokan objekteista tulee kopiointikelvottomia. Tämä on erityisen hyödyllistä, kun luokallamme on osoittimia tai dynaamisesti allokoituja resursseja. Tällaisissa tilanteissa voimme joko kirjoittaa oman kopiokonstruktorin, kuten yllä oleva merkkijonoesimerkki, tai tehdä yksityisen kopion rakentajan, jotta käyttäjät saavat ajon aikana kääntäjävirheitä eikä yllätyksiä.

Miksi argumentti kopiokonstruktorille on välitettävä viitteenä?

Kopiokonstruktori kutsutaan, kun objekti välitetään arvolla. Kopiokonstruktori itsessään on funktio. Joten jos välitämme argumentin arvon mukaan kopiokonstruktorissa, kopiokonstruktorille tehdään kutsu kutsua kopiokonstruktoria, josta tulee päättymätön kutsuketju. Siksi kääntäjä ei salli parametrien välittämistä arvon mukaan.

Miksi kopiokonstruktorin argumentin pitäisi olla const?

Yksi syy läpimenoon konst viittaus on, että meidän pitäisi käyttää konst C++:ssa aina kun mahdollista, jotta objektit eivät muutu vahingossa. Tämä on yksi hyvä syy välittää viittaus as konst , mutta siinä on muutakin kuin ' Miksi kopiokonstruktorin argumentin pitäisi olla const?'