|
|||||||
Конструктор копирования в C++: объяснение и пример использования
Время создания: 13.08.2015 01:25
Текстовые метки: c++, конструктор копирования, пример
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/1439414710chs6b1xcrf/text.html на raw.github.com
|
|||||||
|
|||||||
Конструктор копирования Продолжая начатую тему Конструктор копирования , я приведу пример случая, в котором необходимо создании конструктора копирования. Пример почти такой же, как в википедии куда я ранее ссылался, но чуть проще и немного понятнее для новичков в программировании. Внимание! Не следует путать конструктор копирования и реализацию оператора присваивания (operator=), это разные вещи! Зачем нужен конструктор копирования Вначале нужно показать код: #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"); // Объявляю переменную v, тип которой наша структура и выделяю память для 3 элементов int Array v(3); // Записываю в переменную v значения v.element[0]=20; v.element[1]=30; v.element[2]=40;
// Объявляю переменную x, тип которой наша структура и копирую туда данные из v Array x=v; cout<<x.element[0]<<" "<<x.element[1]<<" "<<x.element[2]<<endl; // Элементы x // Например, появилась необходимость изменить объект v v.element[0]=100; 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(); // Деструктор для освобождения памяти }; // Описание конструктора с параметром типа int вне класса Array::Array(int N) { 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"); // Объявил объект v и указал, что он содержит три элемента Array v(3); // Записал данные в объект 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; } В самый конец вы можете дописать вывод данных первого объекта на экран. В этом коде был использован прием, благодаря которому каждый объект будет обладать своим уникальным указателем. В первом случае была проблема в том, что оба указателя указывают на одно и то же место, значит, чтобы решить проблему, нужно сделать два указателя, которые не будут зависимы друг от друга и будут указывать на разные адреса. Кроме этого нужно учитывать, что при копировании размеры объектов должны совпадать. Чтобы размеры объектов совпадали, я при выделении памяти взял размер из принимаемого объекта и выделил столько памяти, сколько выделено для принимаемого объекта. Не нужно забывать, что при явном использовании конструктора копирования, выполнение копирования наша забота, поэтому копируем необходимые данные своими силами. Я выполнил поэлементное копирование одного массива в другой. После выполнения таких не хитрых операций легко можно работать с обоими объектами, не беспокоясь за то, что изменяя один объект мы навредим внутри другого. Это и есть ответ на вопрос: “Зачем нужен конструктор копирования” Я натыкался на примеры с деструкторами, но мне такие примеры давали больше воды, чем пользы. Такой пример немного нагляднее, понятнее и самое главное хорошо дает понять основные причины использования конструктора копирования. Но примеры ориентированные на деструкторы тоже полезны и нужны. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|