Попередня умова: Конструктор на С++
А конструктор копіювання це функція-член, яка ініціалізує об’єкт за допомогою іншого об’єкта того самого класу. Простіше кажучи, конструктор, який створює об’єкт, ініціалізуючи його об’єктом того самого класу, який був створений раніше, відомий як конструктор копіювання .
Конструктор копіювання використовується для ініціалізації членів новоствореного об’єкта шляхом копіювання членів уже існуючого об’єкта.
Конструктор копіювання приймає посилання на об’єкт того самого класу як аргумент.
Sample(Sample &t) { id=t.id; }> Процес ініціалізації членів об'єкта за допомогою конструктора копіювання відомий як ініціалізація копіювання.
Це також називається почленною ініціалізацією, тому що конструктор копіювання ініціалізує один об’єкт за допомогою існуючого об’єкта, обидва належать до одного класу на базі копіювання член за членом.
Програміст може явно визначити конструктор копіювання. Якщо програміст не визначає конструктор копіювання, компілятор робить це за нас.
приклад:
js onload

Синтаксис конструктора копіювання
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;> }> |
>
>Вихід
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;> }> |
>
>Вихід
1001 Manjeet 10000 1001 Manjeet>
Характеристики Copy Constructor
1. Конструктор копіювання використовується для ініціалізації членів новоствореного об’єкта шляхом копіювання членів уже існуючого об’єкта.
2. Конструктор копіювання приймає посилання на об’єкт того самого класу як аргумент. Якщо ви передаєте об’єкт за значенням у конструктор копіювання, це призведе до рекурсивного виклику самого конструктора копіювання. Це відбувається тому, що передача за значенням передбачає створення копії, а створення копії включає виклик конструктора копіювання, що призводить до нескінченного циклу. Використання посилання дозволяє уникнути цієї рекурсії. Тому ми використовуємо посилання на об’єкти, щоб уникнути нескінченних викликів.
Sample(Sample &t) { id=t.id; }> 3. Процес ініціалізації членів об'єкта через конструктор копіювання відомий як ініціалізація копіювання.
4 . Його також називають почленною ініціалізацією, тому що конструктор копіювання ініціалізує один об’єкт за допомогою існуючого об’єкта, обидва належать до одного класу на основі почленного копіювання.
5. Програміст може явно визначити конструктор копіювання. Якщо програміст не визначає конструктор копіювання, компілятор робить це за нас.
приклад:
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;> }> |
>
сонячний деол вік
>Вихід
p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15>
Типи конструкторів копіювання
1. Конструктор копіювання за замовчуванням
Неявно визначений конструктор копіювання копіюватиме бази та члени об’єкта в тому ж порядку, у якому конструктор ініціалізував би бази та члени об’єкта.
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;> }> |
>
>Вихід
ID=10 ID=10>
2. Визначений користувачем конструктор копіювання
Визначений користувачем конструктор копіювання, як правило, потрібен, коли об’єкт володіє покажчиками або посиланнями, які не підлягають спільному використанню, наприклад на файл, у цьому випадку також слід записати деструктор і оператор присвоєння
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;> }> |
>
>Вихід
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;> }> |
>
>
актор говіндаВихід
1001 Ram 10000 1001 Ram 10000>
Коли викликається конструктор копіювання?
У C++ конструктор копіювання може бути викликаний у таких випадках:
- Коли об’єкт класу повертається за значенням.
- Коли об’єкт класу передається (у функцію) за значенням як аргумент.
- Коли об’єкт створено на основі іншого об’єкта того самого класу.
- Коли компілятор генерує тимчасовий об'єкт.
Однак не гарантовано, що конструктор копіювання буде викликано в усіх цих випадках, оскільки стандарт C++ дозволяє компілятору оптимізувати копіювання в певних випадках, одним із прикладів є оптимізація повернення значення (іноді його називають RVO).
Копія Elision
У elision копіювання компілятор запобігає створенню додаткових копій, що призводить до економії місця та підвищення складності програми (як часу, так і простору); Таким чином код стає більш оптимізованим.
приклад:
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;> }> |
>
>Вихід
GFG! GFG! GFG!>
Тепер компілятор вирішує, що він хоче надрукувати, він може або надрукувати вихідні дані вище, або він може надрукувати випадок 1 або випадок 2 нижче, і ось що Оптимізація повернення вартості є. Простими словами, RVO це техніка, яка дає компілятору деякі додаткові можливості для завершення створеного тимчасового об’єкта, що призводить до зміни спостережуваної поведінки/характеристик кінцевої програми.
Випадок 1:
GFG! GFG!>
Випадок 2:
GFG!>
Коли потрібен визначений користувачем конструктор копіювання?
Якщо ми не визначимо наш власний конструктор копіювання, компілятор C++ створює конструктор копіювання за замовчуванням для кожного класу, який виконує копіювання між об’єктами по членам. Конструктор копіювання, створений компілятором, загалом працює добре. Нам потрібно визначити наш власний конструктор копіювання, лише якщо об’єкт має покажчики або будь-який розподіл ресурсу під час виконання, наприклад дескриптор файлу , підключення до мережі тощо.
За замовчуванням конструктор виконує лише поверхове копіювання.

Глибоке копіювання можливе лише за допомогою конструктора копіювання, визначеного користувачем. У визначеному користувачем конструкторі копіювання ми гарантуємо, що покажчики (або посилання) скопійованих об’єктів вказують на нові місця пам’яті.
Конструктор копіювання проти оператора присвоєння
Основна відмінність між конструктором копіювання та оператором присвоєння полягає в тому, що конструктор копіювання створює нове сховище пам’яті кожного разу, коли він викликається, тоді як оператор присвоєння не створює нового сховища пам’яті.
Який із наступних двох операторів викликає конструктор копіювання, а який — оператор присвоювання?
MyClass t1, t2; MyClass t3 = t1; // ---->(1) t2 = t1; // -----> (2)>
Конструктор копіювання викликається, коли новий об’єкт створюється з існуючого об’єкта як копія існуючого об’єкта. Оператор присвоєння викликається, коли вже ініціалізованому об’єкту присвоюється нове значення з іншого існуючого об’єкта. У наведеному вище прикладі (1) викликає конструктор копіювання, а (2) викликає оператор присвоювання. Перегляньте це для отримання додаткової інформації.
Приклад – клас, де потрібен конструктор копіювання
Нижче наведено повну програму C++ для демонстрації використання конструктора копіювання. У наступному класі String ми повинні написати конструктор копіювання.
приклад:
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;> }> |
>
введення користувача java
>Вихід
GeeksQuiz GeeksQuiz GeeksQuiz techcodeview.com>
Яка буде проблема, якщо ми видалимо конструктор копіювання з наведеного вище коду?
Якщо ми видалимо конструктор копіювання з наведеної вище програми, ми не отримаємо очікуваного результату. Зміни, внесені до str2, також відображаються в str1, чого ніколи не очікується.
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;> }> |
>
>
Вихід:
GeeksQuiz GeeksQuiz techcodeview.com techcodeview.com>
Чи можемо ми зробити конструктор копіювання приватним?
так, конструктор копіювання можна зробити приватним. Коли ми робимо конструктор копіювання приватним у класі, об’єкти цього класу стають непридатними для копіювання. Це особливо корисно, коли наш клас має покажчики або динамічно розподілені ресурси. У таких ситуаціях ми можемо або написати власний конструктор копіювання, як у наведеному вище прикладі String, або створити приватний конструктор копіювання, щоб користувачі отримували помилки компілятора, а не сюрпризи під час виконання.
Чому аргумент конструктора копіювання потрібно передати як посилання?
Конструктор копіювання викликається, коли об’єкт передається за значенням. Конструктор копіювання сам по собі є функцією. Отже, якщо ми передаємо аргумент за значенням у конструкторі копіювання, буде зроблено виклик конструктора копіювання для виклику конструктора копіювання, який стає незавершеним ланцюжком викликів. Тому компілятор не дозволяє передавати параметри за значенням.
Чому аргумент конструктора копіювання має бути const?
Одна з причин проходження конст це посилання, яке ми повинні використовувати конст у C++, де це можливо, щоб об’єкти не були випадково змінені. Це одна з вагомих причин передати посилання як конст , але це більше, ніж ' Чому аргумент для конструктора копіювання має бути const?»