logo

Kopiera Constructor i C++

Nödvändig förutsättning: Konstruktör i C++

A kopia konstruktör är en medlemsfunktion som initierar ett objekt med ett annat objekt av samma klass. Enkelt uttryckt kallas en konstruktor som skapar ett objekt genom att initiera det med ett objekt av samma klass, som har skapats tidigare, en kopia konstruktör .



Kopieringskonstruktorn används för att initiera medlemmarna i ett nyskapat objekt genom att kopiera medlemmarna i ett redan existerande objekt.

Copy constructor tar en referens till ett objekt av samma klass som ett argument.

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

Processen att initiera medlemmar av ett objekt genom en kopieringskonstruktor kallas kopieringsinitiering.



Det kallas också medlemsvis initiering eftersom kopieringskonstruktören initierar ett objekt med det befintliga objektet, båda tillhör samma klass på basis av medlem för medlem kopia.

Kopieringskonstruktorn kan definieras explicit av programmeraren. Om programmeraren inte definierar kopieringskonstruktorn gör kompilatorn det åt oss.

Exempel:



inställningsmeny android
Syntax för Copy Constructor med exempel

Syntax för 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>

Egenskaper för Copy Constructor

1. Kopieringskonstruktorn används för att initiera medlemmarna i ett nyskapat objekt genom att kopiera medlemmarna i ett redan existerande objekt.

2. Copy constructor tar en referens till ett objekt av samma klass som ett argument. Om du skickar objektet efter värde i kopieringskonstruktorn, skulle det resultera i ett rekursivt anrop till själva kopieringskonstruktorn. Detta händer eftersom överföring av värde innebär att man gör en kopia, och att göra en kopia innebär att man anropar kopieringskonstruktorn, vilket leder till en oändlig loop. Genom att använda en referens undviks denna rekursion. Så vi använder referens av objekt för att undvika oändliga anrop.

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

3. Processen att initiera medlemmar av ett objekt genom en kopieringskonstruktor kallas kopieringsinitiering.

4 . Det kallas också medlemsvis initiering eftersom kopieringskonstruktören initierar ett objekt med det befintliga objektet, båda tillhör samma klass på en kopia-basis för medlem.

5. Kopieringskonstruktorn kan definieras explicit av programmeraren. Om programmeraren inte definierar kopieringskonstruktorn gör kompilatorn det åt oss.

Exempel:

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 av kopieringskonstruktörer

1. Standardkopieringskonstruktör

En implicit definierad kopieringskonstruktor kommer att kopiera baserna och medlemmarna av ett objekt i samma ordning som en konstruktör skulle initiera baserna och medlemmarna i objektet.

C++




katalog i linux-kommandon

// 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. Användardefinierad kopieringskonstruktör

En användardefinierad kopieringskonstruktor behövs vanligtvis när ett objekt äger pekare eller icke-delbara referenser, till exempel till en fil, i vilket fall en destruktor och en tilldelningsoperator också bör skrivas

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

>

>

Produktion

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

>

>

Produktion

 1001 Ram 10000 1001 Ram 10000>

När kallas kopieringskonstruktorn?

I C++ kan en Copy Constructor anropas i följande fall:

  • När ett objekt i klassen returneras av värde.
  • När ett objekt i klassen skickas (till en funktion) av värde som ett argument.
  • När ett objekt är konstruerat utifrån ett annat objekt av samma klass.
  • När kompilatorn genererar ett temporärt objekt.

Det är dock inte garanterat att en kopia konstruktör kommer att anropas i alla dessa fall, eftersom C++ Standard tillåter kompilatorn att optimera bort kopian i vissa fall, ett exempel är optimering av avkastningsvärde (ibland kallad RVO).

Kopiera Elision

I copy elision förhindrar kompilatorn att det görs extra kopior vilket resulterar i att spara utrymme och förbättra programmets komplexitet (både tid och utrymme); Därför görs koden mer optimerad.

lista på java

Exempel:

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 är det på kompilatorn att bestämma vad den vill skriva ut, den kan antingen skriva ut ovanstående utdata eller så kan den skriva ut fall 1 eller fall 2 nedan, och detta är vad Return Value Optimization är. Med enkla ord, RVO är en teknik som ger kompilatorn ytterligare kraft att avsluta det tillfälliga objektet som skapats, vilket resulterar i att det slutliga programmets observerbara beteende/egenskaper ändras.

Fall 1:

GFG! GFG!>

Fall 2:

GFG!>

När behövs en användardefinierad kopieringskonstruktor?

Om vi ​​inte definierar vår egen kopieringskonstruktor skapar C++-kompilatorn en standardkopiakonstruktor för varje klass som gör en medlemsvis kopiering mellan objekt. Den kompilatorskapade kopia-konstruktorn fungerar bra i allmänhet. Vi behöver bara definiera vår egen kopieringskonstruktor om ett objekt har pekare eller någon runtime allokering av resursen som ett filhandtag , en nätverksanslutning osv.

Standarden konstruktören gör endast ytlig kopia.

grund kopia i C++

Djupkopiering är endast möjligt med en användardefinierad kopieringskonstruktor. I en användardefinierad kopieringskonstruktor ser vi till att pekare (eller referenser) för kopierade objekt pekar på nya minnesplatser.

Deep Copy i C++

Kopiera konstruktör vs uppdragsoperatör

Huvudskillnaden mellan Copy Constructor och Assignment Operator är att Copy-konstruktorn skapar en ny minneslagring varje gång den anropas medan uppdragsoperatören inte skapar ny minneslagring.

Vilken av följande två påståenden anropar kopiekonstruktorn och vilken anropar uppdragsoperatören?

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

En kopia konstruktor anropas när ett nytt objekt skapas från ett befintligt objekt, som en kopia av det befintliga objektet. Tilldelningsoperatorn anropas när ett redan initierat objekt tilldelas ett nytt värde från ett annat befintligt objekt. I exemplet ovan anropar (1) kopiekonstruktorn och (2) anropar tilldelningsoperatören. Se detta för mer information.

Exempel – Klass där en kopiakonstruktör krävs

Följande är ett komplett C++-program för att demonstrera användningen av Copy-konstruktorn. I följande String-klass måste vi skriva en kopiakonstruktor.

Exempel:

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>

Vad skulle vara problemet om vi tar bort kopieringskonstruktorn från ovanstående kod?

Om vi ​​tar bort kopieringskonstruktorn från ovanstående program får vi inte den förväntade utdata. Ändringarna i str2 återspeglas också i str1, vilket aldrig förväntas.

C++




sträng till boolesk java

#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öra kopieringskonstruktören privat?

Ja, en kopia konstruktör kan göras privat. När vi gör en kopieringskonstruktor privat i en klass, blir objekt i den klassen omöjliga att kopiera. Detta är särskilt användbart när vår klass har pekare eller dynamiskt allokerade resurser. I sådana situationer kan vi antingen skriva vår egen kopiakonstruktor som ovanstående String-exempel eller göra en privat kopiakonstruktor så att användare får kompilatorfel snarare än överraskningar under körning.

Varför måste argument till en kopiakonstruktor skickas som referens?

En kopia konstruktor anropas när ett objekt skickas av värde. Copy constructor i sig är en funktion. Så om vi skickar ett argument efter värde i en kopieringskonstruktor, skulle ett anrop till kopieringskonstruktorn göras för att anropa kopieringskonstruktorn som blir en icke-avslutande kedja av anrop. Därför tillåter inte kompilatorn att parametrar skickas efter värde.

Varför argument till en kopia konstruktor bör vara const?

En anledning till att passera konst referens är att vi bör använda konst i C++ där det är möjligt så att objekt inte ändras av misstag. Detta är ett bra skäl för att passera referens som konst , men det finns mer i det än ' Varför ska argumentet till en kopiakonstruktor vara const?'