Requisit previ: Constructor en C++
A constructor de còpia és una funció membre que inicialitza un objecte utilitzant un altre objecte de la mateixa classe. En termes simples, un constructor que crea un objecte inicialitzant-lo amb un objecte de la mateixa classe, que s'ha creat anteriorment, es coneix com a constructor de còpia .
El constructor de còpia s'utilitza per inicialitzar els membres d'un objecte acabat de crear copiant els membres d'un objecte ja existent.
El constructor de còpia pren una referència a un objecte de la mateixa classe com a argument.
Sample(Sample &t) { id=t.id; }> El procés d'inicialització dels membres d'un objecte mitjançant un constructor de còpia es coneix com a inicialització de còpia.
També s'anomena inicialització per membres perquè el constructor de còpia inicialitza un objecte amb l'objecte existent, tots dos pertanyents a la mateixa classe per còpia de membre per membre.
El programador pot definir explícitament el constructor de còpia. Si el programador no defineix el constructor de còpia, el compilador ho fa per nosaltres.
Exemple:
proves de rendiment

Sintaxi de 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;> }> |
>
>Sortida
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;> }> |
>
>Sortida
1001 Manjeet 10000 1001 Manjeet>
Característiques de Copy Constructor
1. El constructor de còpia s'utilitza per inicialitzar els membres d'un objecte acabat de crear copiant els membres d'un objecte ja existent.
2. El constructor de còpia pren una referència a un objecte de la mateixa classe com a argument. Si passeu l'objecte per valor al constructor de còpia, es produiria una crida recursiva al propi constructor de còpia. Això passa perquè passar per valor implica fer una còpia, i fer una còpia implica cridar el constructor de còpia, donant lloc a un bucle infinit. L'ús d'una referència evita aquesta recursivitat. Així que fem servir la referència d'objectes per evitar trucades infinites.
Sample(Sample &t) { id=t.id; }> 3. El procés d'inicialització dels membres d'un objecte mitjançant un constructor de còpia es coneix com inicialització de còpia.
4 . També s'anomena inicialització per membres perquè el constructor de còpies inicialitza un objecte amb l'objecte existent, tots dos pertanyents a la mateixa classe en una còpia de membre per membre.
5. El programador pot definir explícitament el constructor de còpia. Si el programador no defineix el constructor de còpia, el compilador ho fa per nosaltres.
Exemple:
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;> }> |
>
>Sortida
p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>
Tipus de constructors de còpia
1. Constructor de còpia per defecte
Un constructor de còpia definit implícitament copiarà les bases i els membres d'un objecte en el mateix ordre que un constructor inicialitzaria les bases i els membres de l'objecte.
matriu en mètodes java
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;> }> |
>
>Sortida
ID=10 ID=10>
2. Constructor de còpies definides per l'usuari
Generalment es necessita un constructor de còpia definit per l'usuari quan un objecte posseeix punters o referències no compartibles, com ara un fitxer, en aquest cas també s'hauria d'escriure un destructor i un operador d'assignació.
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;> }> |
>
>Sortida
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;> }> |
>
>Sortida
1001 Ram 10000 1001 Ram 10000>
Quan es diu el constructor de còpia?
En C++, es pot cridar un constructor de còpia en els casos següents:
en java
- Quan un objecte de la classe es retorna per valor.
- Quan un objecte de la classe es passa (a una funció) per valor com a argument.
- Quan un objecte es construeix a partir d'un altre objecte de la mateixa classe.
- Quan el compilador genera un objecte temporal.
Tanmateix, no es garanteix que es cridi a un constructor de còpia en tots aquests casos, perquè l'estàndard C++ permet al compilador optimitzar la còpia en determinats casos, un exemple és el optimització del valor de retorn (de vegades es coneix com a RVO).
Copia Elisió
En l'elisió de còpies, el compilador impedeix fer còpies addicionals que es tradueix en estalvi d'espai i millora la complexitat del programa (tant en temps com en espai); Per tant, el codi és més optimitzat.
Exemple:
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;> }> |
>
>Sortida
GFG! GFG! GFG!>
Ara és al compilador decidir què vol imprimir, podria imprimir la sortida anterior o podria imprimir el cas 1 o el cas 2 a continuació, i això és el que Optimització del valor de retorn és. En paraules senzilles, RVO és una tècnica que dóna al compilador una mica de poder addicional per finalitzar l'objecte temporal creat, la qual cosa resulta en canviar el comportament/característiques observables del programa final.
Cas 1:
GFG! GFG!>
Cas 2:
GFG!>
Quan es necessita un constructor de còpia definit per l'usuari?
Si no definim el nostre propi constructor de còpia, el compilador C++ crea un constructor de còpia predeterminat per a cada classe que fa una còpia per membres entre objectes. El constructor de còpia creat pel compilador funciona bé en general. Hem de definir el nostre propi constructor de còpies només si un objecte té punters o qualsevol assignació en temps d'execució del recurs un controlador d'arxiu , una connexió de xarxa, etc.
El valor per defecte el constructor només fa còpies superficials.

La còpia profunda només és possible amb un constructor de còpia definit per l'usuari. En un constructor de còpia definit per l'usuari, ens assegurem que els punters (o referències) dels objectes copiats apunten a noves ubicacions de memòria.
Constructor de còpia vs Operador d'assignació
La principal diferència entre el constructor de còpia i l'operador d'assignació és que el constructor de còpia fa un nou emmagatzematge de memòria cada vegada que es crida mentre que l'operador d'assignació no fa un nou emmagatzematge de memòria.
Quina de les dues sentències següents anomena el constructor de còpia i quina l'operador d'assignació?
MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = t1; // -----> (2)>>>Es crida un constructor de còpia quan es crea un objecte nou a partir d'un objecte existent, com a còpia de l'objecte existent. L'operador d'assignació es crida quan a un objecte ja inicialitzat se li assigna un valor nou d'un altre objecte existent. A l'exemple anterior (1) crida al constructor de còpia i (2) a l'operador d'assignació. Consulteu això per obtenir més detalls.
Exemple: classe on es requereix un constructor de còpia
A continuació es mostra un programa C++ complet per demostrar l'ús del constructor Copy. A la següent classe String, hem d'escriure un constructor de còpia.
Exemple:
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;> }> |
>Sortida
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>
Quin seria el problema si eliminem el constructor de còpia del codi anterior?
Si eliminem el constructor de còpia del programa anterior, no obtindrem la sortida esperada. Els canvis fets a str2 també es reflecteixen a str1, cosa que mai s'espera.
C++
log4j
#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;> }> |
>
>
Sortida:
GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>
Podem fer privat el constructor de còpies?
Sí, un constructor de còpies es pot fer privat. Quan fem privat un constructor de còpies en una classe, els objectes d'aquesta classe esdevenen no copiables. Això és especialment útil quan la nostra classe té punters o recursos assignats dinàmicament. En aquestes situacions, podem escriure el nostre propi constructor de còpia com l'exemple String anterior o fer un constructor de còpia privada perquè els usuaris tinguin errors del compilador en lloc de sorpreses en temps d'execució.
Per què s'ha de passar l'argument a un constructor de còpia com a referència?
Es crida un constructor de còpia quan es passa un objecte per valor. El propi constructor de còpia és una funció. Així, si passem un argument per valor en un constructor de còpia, es faria una crida al constructor de còpia per cridar el constructor de còpia que es converteix en una cadena de trucades que no s'acaba. Per tant, el compilador no permet que els paràmetres es passin per valor.
Per què l'argument d'un constructor de còpia hauria de ser const?
Un motiu per passar const referència és, que hauríem d'utilitzar const en C++ sempre que sigui possible perquè els objectes no es modifiquin accidentalment. Aquesta és una bona raó per passar la referència com a const , però hi ha més que ' Per què l'argument a un constructor de còpia hauria de ser const?'