Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Глава 19. Копирующий конструктор 203
delete
protected: char
int main(int argcs, char* Person ("Randy"); Person p2 = // Вызов копирующего конструктора return 0; } В этом примере конструктор для Person выделит память из кучи для хранения в ней имени произвольной длины, что невозможно при использовании массивов. Де- структор возвращает эту память в кучу. Основная программа создает объект опи- сывающий человека, после чего создается копия этого объекта — р2. После запуска этой программы вы получите сообщение только от одного конст- руктора. Это неудивительно, поскольку копия р2 создается с помощью предоставляе- мого C++ конструктора копирования по умолчанию, а он не выводит никаких сооб- щений. Однако, после того как и р2 выходят из области видимости, вы не получи- те двух сообщений о ликвидации объектов, как можно было ожидать. Более того, если вы выполните эту программу в пошаговом режиме в каком-либо отладчике, то получите сообщение об ошибке. Что же происходит? Конструктор вызывается один раз и выделяет блок памяти из кучи для хранения в нем имени человека. Копирующий конструктор, создаваемый C++, просто копирует этот адрес в новый объект, без выделения нового блока памяти. Когда объекты ликвидируются, деструктор для р2 первым получает доступ к этому блоку памяти. Этот деструктор стирает имя и освобождает блок памяти. К тому времени как деструктор получает доступ к этому блоку, память уже очищена, а имя стерто. Теперь понятно, откуда взялось сообщение об ошибке. Суть проблемы проиллюстриро- вана на рис. 19.1. Объект копируется в новый объект р2, но не копируются исполь- зуемые им ресурсы. Таким образом, и р2 указывают на один и тот же ресурс (в дан- ном случае это блок памяти). Такое явление называется "мелким" (shallow) копировани- ем, поскольку при этом копируются только члены класса как таковые.
р1 р1 pName
С До копирования
pName
pName
Куча
Послекопирования Рис. Мелкое копирование объекта в р2 204 Часть "Классическое"программи Для решения указанной проблемы нужен такой копирующий конструктор, кото- рый будет выделять ресурсы для нового объекта. Давайте добавим такой конструктор к классу и посмотрим, как он работает. class Person (
//копирующий конструктор выделяет новый памяти из кучи p) { << "Копируем " << " в отдельный new + if != 0) i
остальное оставляем без Здесь копирующий конструктор выделяет новый блок памяти для имени, а затем копирует содержимое блока памяти исходного объекта в этот новый блок (рис. 19,2). Такое копирование называется "глубоким" (deep), поскольку копирует не только эле- менты, но и занятые ими ресурсы (конечно, аналогия, как говорится, притянута за уши, но ничего не поделаешь не я придумал эти термины).
Р1 pName pName
Р2 pName
До копирования Послекопирования
Рис. 19.2. Глубокое копирование в р2 Запуск программы с новым копирующим конструктором приведет к выводу на эк- ран следующих строк: Создаем Randy Копируем Randy в отдельный блок Ликвидируем Randy Ликвидируем Randy |
Последнее изменение этой страницы: 2019-04-19; Просмотров: 200; Нарушение авторского права страницы