Мелкая копия и глубокая копия
В классе Circle (пример конструктора копирования, описанный в предыдущем разделе), стратегия копирования согласуется со стратегией системы по умолчанию, то есть члены исходного объекта последовательно копируются в соответствующие члены нового объекта. В таком случае, почему мы все еще хотим определить это сами? Причина в том, что простая инициализация всех ситуаций таким простым способом неизбежно приведет к проблемам в различных ситуациях.
Например, в классе Circle, если к переменной-члену добавляется член-указатель и во время инициализации необходимо динамически выделять память, возникает огромный риск для безопасности. Код выглядит следующим образом:
/************************************//Описание: Программа поддержки учебников по C++//Автор: Хуан //Авторское право:www.dotcpp.com//Date:2017/8/26****************************** ** ******/#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);~Circle(); );doublegirth();};Circle::~Circle(){delete[]str;}Circle::Circle(doubleR,char*str){cout<<Constructor<<endl;this->R=R ;this ->str=newchar[strlen(str)+1];strcpy(this->str,str);cout<<this->R<<<<this->str<<endl;}doubleCircle::area () {returnPI*R*R;}doubleCircle::girth(){return2*PI*R;}intmain(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
Для проверки в классе Circle мы добавили член-указатель и инициализировали его в конструкторе без специального конструктора копирования. Затем в основной функции предложение Circle B(A); присваивает объект A объекту B и вызывает созданный по умолчанию конструктор копии. После запуска программа сообщает об ошибке, как показано ниже:
Фактическая причина заключается в том, что конструктор копирования по умолчанию выполняет только присвоение данных и не может открыть пространство памяти для указателей, что эквивалентно коду:
Это->стр=стр;
По сути, два указателя указывают на часть кучи. Это противоречило нашему первоначальному намерению. Тогда в конце программы, когда два объекта будут переработаны, будут вызваны их собственные деструкторы, чтобы освободить это пространство памяти. Поскольку два объекта нужно вызвать дважды, то есть дважды удалить , произойдет ошибка!
Следовательно, когда в классе есть тип указателя, использование метода конструктора копирования по умолчанию больше не может удовлетворить наши потребности. Необходимо определить конкретный конструктор копирования, который может не только копировать данные, но и выделять пространство памяти для членов. Для достижения реального копирования, также называемого глубоким копированием, используется конструктор глубокого копирования .
Реализация конструктора глубокой копии:
#include<iostream>#include<Cstring>usingnamespacestd;#definePI3.1415classCircle{private:doubleR;char*str;public:Circle(doubleR,char*str);Circle(Circle&A);~Circle();doublerea(); doublegirth();};Circle::~Circle(){delete[]str;cout<<CallDestructor<<endl;}Circle::Circle(Circle&A){cout<<CopyConstructor<<endl;this->R=AR ;this->str=newchar[strlen(A.str)+1];strcpy(this->str,A.str);}Circle::Circle(doubleR,char*str){cout<<Конструктор<<endl ;this->R=R;this->str=newchar[strlen(str)+1];strcpy(this->str,str);}doubleCircle::area(){returnPI*R*R;}doubleCircle: :girth(){return2*PI*R;}intmain(){CircleA(5,NO.1Oldclass);CircleB(A);return0;}
Принцип реализации аналогичен конструктору с параметрами. Перед назначением открывается достаточное пространство памяти для действительного завершения полной копии. Это так называемая «глубокая копия». Пожалуйста, поймите и попробуйте это на компьютере!