На этом шаге мы рассмотрим особенности работы с указателями и конструкторами типа auto_ptr.
Тип auto_ptr поддерживает семантику строгой принадлежности. Иначе говоря, поскольку тип auto_ptr удаляет объект, на который он ссылается, этот объект не может "принадлежать" другим объектам. Два и более экземпляра auto_ptr не должны одновременно быть владельцами одного объекта. К сожалению, в программе такая ситуация не исключена (например, если два экземпляра auto_ptr инициализируются одним и тем же объектом). Программист обязан позаботиться о том, чтобы этого не случилось.
Возникает вопрос: как работают копирующий конструктор и оператор присваивания типа auto_ptr? В обычном варианте эти операции копируют данные из одного объекта auto_ptr в другой, но в нашем случае это создает ситуацию, при которой один объект принадлежит сразу двум экземплярам auto_ptr. Проблема решается просто, но у этого решения есть одно важное следствие: копирующий конструктор и оператор присваивания передают "право владения" тем объектом, на который ссылается auto_ptr.
Рассмотрим следующий пример использования копирующего конструктора:
// Инициализация auto_ptr новым объектом std::auto_ptr<ClassA> ptr1(new ClassA); // Копирование auto_ptr // - право владения объектом передается от ptr1 к ptr2 std::auto_ptr<ClassA> ptr2(ptr1);
После выполнения первой команды объект, созданный оператором new, принадлежит ptr1. Вторая команда передает npaво владения от ptr1 к ptr2. Следовательно, после выполнения второй команды объект, созданный оператором new, принадлежит ptr2, a ptr1 перестает быть владельцем этого объекта. Объект, созданный конструкцией new ClassA, удаляется только один раз - при уничтожении ptr2.
Оператор присваивания поступает аналогичным образом:
// Инициализация auto_ptr новым обьектом std::auto_ptr<ClassA> ptr1(new ClassA); std::auto_ptr<ClassA> ptr2; // Создание другого экземпляра auto_ptr ptr2 = ptr1; // Присваивание auto_ptr // - принадлежность объекта передается от ptr1 к ptr2
Обратите внимание: смена владельца не является простым копированием. Во всех случаях передачи права владения предыдущий владелец (ptr1 в нашем примере) перестает им быть. В результате после передачи права владения предыдущий владелец содержит null-указатель. Подобное поведение серьезно противоречит общим принципам инициализации и присваивания в языках программирования. Копирующий конструктор модифицирует объект, используемый для инициализации нового объекта, а оператор присваивания модифицирует правую часть операции присваивания. Программист должен сам следить за тем, чтобы программа не пыталась разыменовать экземпляр auto_ptr, переставший владеть объектом и содержащий null-указатель.
Новое значение, присваиваемое auto_ptr, также должно относиться к типу auto_ptr. Присваивание обычных указателей не допускается:
std::auto_ptr<ClassA> ptr; // Создание auto_ptr ptr = new ClassA; // ОШИБКА ptr = std::auto_ptr<ClassA>(new ClassA); // ОК. Удаление старого объекта // и получение нового.
На следующем шаге мы рассмотрим источник и приемник auto_ptr.