MyTetra Share
Делитесь знаниями!
О, смотри-ка какое хорошее место. Дайте два!
Конструктор копирования в C++: объяснение и пример использования
13.08.2015
01:25
Текстовые метки: c++, конструктор копирования, пример
Раздел: Компьютер - Программирование - Язык C++

Конструктор копирования


Продолжая начатую тему Конструктор копирования, я приведу пример случая, в котором необходимо создании конструктора копирования. Пример почти такой же, как в википедии куда я ранее ссылался, но чуть проще и немного понятнее для новичков в программировании.


Зачем нужен конструктор копирования


Вначале нужно показать код:



#include <iostream.h>

#include <stdlib.h>

/*СТРУКТУРА МАССИВ*/

struct Array

{

int *element; //Указатель на int

Array(int N); //Конструктор структуры, принимающий параметр типа int

~Array(); //Деструктор структуры для освобождения памяти

};

Array::Array(int N) //Описываю конструктор вне структуры

{

element=new int[N]; //При каждом новом вызове будет выделяться новый участок памяти размером согласно принимаемому параметру

}

Array::~Array() //Описываю деструктор вне структуры

{

delete []element; //Освобождаю память, выделенную внутри конструктора

}

int main()

{

system("CLS");

Array v(3); //Объявляю переменную v, тип которой наша структура и выделяю память для 3 элементов int

v.element[0]=20; //Записываю в переменную v значения

v.element[1]=30;

v.element[2]=40;

Array x=v; //Объявляю переменную x, тип которой наша структура и копирую туда данные из v

cout<<x.element[0]<<" "<<x.element[1]<<" "<<x.element[2]<<endl; //Вывожу на экран элементы x

v.element[0]=100; //Например, появилась необходимость изменить объект v

cout<<x.element[0]<<" "<<x.element[1]<<" "<<x.element[2]<<endl; //Вывожу на экран элементы x

cin.get();

return 0;

}


Если вы плохо знакомы с указателями, то выполнение этого кода может произойти слегка не так, как вы ожидали. Несмотря на то, что и в первом и во втором случае, я вывожу на экран только данные второго созданного мною объекта, не изменяя его напрямую, данные в нем изменились после изменения данных в первом объекте. Такое поведение работы программы объясняется тем, что срабатывает конструктор копирования по умолчанию. Этот конструктор копирования копирует указатель как указатель и получается, что в обоих объектах оба указателя указывают на один и тот же адрес. То есть если изменить данные, расположенные на том адресе, то и первый и второй объект будут получать те измененные данные. Думаю, суть вы должны уловить. Вот в таких случаях и возникает вопрос безопасного копирования данных из одного объекта в другой. Безопасное копирование в этом случае обозначает, что изменения одного из объектов не должны влиять на другой объект. Для решения этого вопроса как раз и используют конструктор копирования.


Код с конструктором копирования


#include <iostream.h>

#include <stdlib.h>

/*СТРУКТУРА МАССИВ*/

struct Array

{

int *element; //Указатель на int

int size; //Размер массива

Array(int N); //Конструктор принимает параметр, по которому определяет количество элементов для массива

Array(Array &obj); //Конструктор копирования

~Array(); //Деструктор для освобождения памяти

};

Array::Array(int N) //Описываю конструктор с параметром типа int вне класса

{

element=new int[N]; //При каждом новом вызове выделяю память для N элементов типа int

size=N; //Запоминаю размер согласно указанному параметру

}

Array::Array(Array &obj) //Описываю конструктор копирования вне класса

{

element=new int[obj.size]; //Выделяю память для элемента объекта

for (int i=0;i<obj.size;i++) element[i]=obj.element[i]; //Поэлементно копирую каждый элемент из принимаемого объекта в текущий

size=obj.size; //скопировать нужно каждый кусочек класса, сами они не копируются

}

Array::~Array() //Описываю деструктор вне класса

{

delete []element; //Освобождаю память

}

int main()

{

system("CLS");

Array v(3); //Объявил объект v и указал, что он содержит три элемента

v.element[0]=20; //Записал данные в объект

v.element[1]=30;

v.element[2]=40;

Array x=v; //Объявляю второй объект и копирую в него данные из первого

cout<<x.element[0]<<" "<<x.element[1]<<" "<<x.element[2]<<endl; //Вывожу данные второго объекта на экран

v.element[0]=100; //Меняю одно поле первого объекта

cout<<x.element[0]<<" "<<x.element[1]<<" "<<x.element[2]<<endl; //Вывожу данные второго объекта на экран

cin.get();

return 0;

}


В самый конец вы можете дописать вывод данных первого объекта на экран. В этом коде был использован прием, благодаря которому каждый объект будет обладать своим уникальным указателем. В первом случае была проблема в том, что оба указателя указывают на одно и то же место, значит, чтобы решить проблему, нужно сделать два указателя, которые не будут зависимы друг от друга и будут указывать на разные адреса. Кроме этого нужно учитывать, что при копировании размеры объектов должны совпадать. Чтобы размеры объектов совпадали, я при выделении памяти взял размер из принимаемого объекта и выделил столько памяти, сколько выделено для принимаемого объекта. Не нужно забывать, что при явном использовании конструктора копирования, выполнение копирования наша забота, поэтому копируем необходимые данные своими силами. Я выполнил поэлементное копирование одного массива в другой.

После выполнения таких не хитрых операций легко можно работать с обоими объектами, не беспокоясь за то, что изменяя один объект мы навредим внутри другого. Это и есть ответ на вопрос: “Зачем нужен конструктор копирования”

Я натыкался на примеры с деструкторами, но мне такие примеры давали больше воды, чем пользы. Такой пример немного нагляднее, понятнее и самое главное хорошо дает понять основные причины использования конструктора копирования. Но примеры ориентированные на деструкторы тоже полезны и нужны


Так же в этом разделе:
← Содержание ...
 
MyTetra Share v.0.35
Яндекс индекс цитирования