Программирование >>  Операторы преобразования типа 

1 ... 10 11 12 [ 13 ] 14 15 16 ... 239


Команда delete и секция catch стали лишними. Интерфейс указателя auto ptr почти не отличается от интерфейса обычного указателя; оператор * производит разыменование объекта, на который ссылается указатель, а оператор -> предоставляет доступ к членам класса или струюуры. Математические операции с указателями (такие, как ++) для auto ptr не определены. Впрочем, это скорее достоинство, нежели недостаток, потому что вычисления с указателями слиптом часто приводят к неприятностям.

Учтите, что тип auto ptr не позволяет инициализировать объект обычным указателем в конструкции присваивания. Инициализация auto ptr должна производиться напрямую по значению:

std::auto ptr<ClassA> ptrl(new ClassA): OK

std::autoj)tr<ClassA> ptr2 = new ClassA; ОШИБКА

Передача прав владения в auto ptr

Тип auto ptr поддерживает семантику строгой принадлежности. Иначе говоря, поскольку тип auto ptr удаляет объект, на который он ссылается, этот объект не может принадлежать другим объектам. Два и более экземпляра auto ptr не должны одновременно быть владельцами одного объекта. К сожалению, в программе такая ситуация не исключена (например, если два экземпляра auto ptr инициализируются одним и тем же объектом). Программист обязан позаботиться о том, чтобы этого не случилось.

Возникает вопрос: как работают копирующий конструктор и оператор присваивания типа auto ptr? В обычном варианте эти операции копируют данные из одного объекта auto ptr в другой, но в нашем случае это создает ситуацию, при которой один объект принадлежит сразу двум экземплярам auto ptr. Проблема решается просто, но у этого решения есть одно важное следствие: копирующий конструктор и оператор присваивания передают -вправо владения тем объектом, на который ссылается auto ptr.

Рассмотрим следующий пример использования копирующего конструктора:

Инициализация auto ptr новым объектом std::autoj)tr<ClassA> ptrl(new ClassA):

Копирование auto ptr

- право владения объектом передается от ptrl к ptr2 std:;autoj)tr<ClassA> ptr2(ptrl):

После выполнения первой команды объект, созданный оператором new, принадлежит ptrl. Вторая команда передает право владения от ptrl к ptr2. Следова-

Между следующими двумя фрагментами существует тонкое различие:

X X;

Y у(х); Явное преобразование и

X х:

Y у = х; Неявное преобразование



телыю, после выполнения второй команды объект, созданный оператором new, принадлежит ptr2, а ptrl перестает быть владельцем этого объекта. Объект, созданный конструкцией new ClassA, удаляется только один раз - при уничтожении ptr2.

Оператор присваивания поступает аналогичным образом:

Инициализация auto ptr новым обьектом std: ;auto ptr<ClassA> ptrKnew ClassA);

std::auto ptr<ClassA> ptr2: Создание другого экземпляра auto ptr

ptr2 = ptrl: Присваивание auto ptr

- принадлежность объекта передается от ptrl к ptr2

Обратите внимание: смена владельца пе является простым копированием. Во всех случаях передачи нрава владения предыдущий владелец (ptrl в нашем примере) перестает им быть, В результате после передачи права владения предыдущий владелец содержит null-указатель. Подобное поведение серьезно противоречит общим принципам инициализации и присваивания в языках программирования. Копирующий конструктор модифицирует объект, используемый для инициализации нового объекта, а оператор присваивания модифицирует правую часть операции присваивания. Программист должен сам следить за тем, чтобы программа не пыталась разыменовать экземпляр autojDtr, переставший владеть объектом и содержащий null-указатель.

Новое значение, присваиваемое auto ptr, также должно относиться к типу auto ptr. Присваивание обычных указателей не допускается:

std::auto ptr<ClassA> ptr; Создание auto ptr

ptr - new ClassA: ОШИБКА

ptr = std::autoj)tr<ClassA>(new ClassA); OK. удаление старого объекта

и получение нового.

Источник и приемник

Из механизма передачи права владения следует возможность особого применения указателей auto ptr: они могут использоваться функциями для передачи права владения другим функциям. Возможны два разных сценария.

О Функция является приемником данных. Это происходит в том случае, если auto ptr передается функции по значению. В этом случае параметр вызванной функции становится владельцем auto ptr. Следовательно, если функция не произведет обратной передачи, объект будет удален при выходе из функции:

void sink(std::auto ptr<ClassA>); sinkO получает право владения

О Функция является источником данных. При возврате из auto ptr право владения возвращаемого значения передается вызвавшей функции. Методика продемонстрирована в следующем примере:

std::auto ptr<ClassA> f() {



std::auto ptr<ClassA> ptrCnew ClassA); ptr становится владельцем

нового объекта return ptr: Право владения возвращается на сторону вызова

void gO (

std::autoj)tr<ClassA> p;

for (int i=0; i<10; ++i) {

p = f(); lip становится владельцем возвращаемого объекта (предыдущий возвращенный объект уничтожается).

} Удаление последнего объекта, принадлежащего р

При каждом вызове функция f() создает объект оператором new и возвращает его (вместе с правом владения) вызывающей стороне. В результате присваивания значения, возвращаемого функцией, право владения передается переменной р. При второй, третьей и последующих итерациях присваивание р уничтожает объект, ранее принадлежавший р. Выход из д(), а следовательно уничтожение р, приводит к зшичтожению последнего объекта, принадлежащего р. В любом случае утечка ресурсов невозможна. Даже при возникновении исключения экземпляр autojDtr, владеющий объектом, обеспечит его уничтожение.

П реду п режд ен ие

Семантика auto ptr всегда предполагает владение объектом, поэтому не используйте auto ptr в параметрах или возвращаемом значении, если вы не собираетесь передавать право владения. Для примера рассмотрим наивную реализацию функции вывода объекта, на который ссылается auto ptr. Попытка применить такую функцию на практике закончится катастрофой.

ПЛОХОЙ ПРИМЕР template <class Т>

void bad print(std::auto ptr<T> p) p становится владельцем { переданного аргумента

Указывает ли р на объект?

1f (p.getO == NULL) { Std::cout NULL ;

else {

std::cout *p:

} Ошибка - обьект. на который ссылается р.

удаляется при выходе из функции.

Каждый раз, когда этой реализации badjDrint передается аргумент типа auto ptr, принадлежащий ему объект (если он есть) уничтожается. Дело в том, что вместе со значением аргумента параметру р передается право владения объектом autojrtr, а объект, принадлежащий р, удаляется при выходе из функции. Вряд ли про-



1 ... 10 11 12 [ 13 ] 14 15 16 ... 239

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика