Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Глава 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; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.01 с.)
Главная | Случайная страница | Обратная связь