|
Программирование >> Перегруженные имена функций и идентификаторы
За исключением того случая, когда вы использовали синтаксис размещения для оператора new, вам следует просто удалять объекты при помощи delete, а не вызывать явно деструктор. Предположим, что вы создали объект при помощи обычного new: Fred* p = new Fred(); В таком случае деструктор Fred::~Fred() будет автоматически вызван, когда вы удаляете объект: delete p; Вызывает p->~Fred() Вам не следует явно вызывать деструктор, поскольку этим вы не освобождаете память, выделенную для объекта Fred. Помните: delete p делает сразу две вещи: вызывает деструктор и освобождает память. Что такое синтаксис размещения new ( placement new ) и зачем он нужен? Есть много случаев для использования синтаксиса размещения для new. Самое простое - вы можете использовать синтаксис размещения для помещения объекта в определенное место в памяти. Для этого вы указываете место, передавая указатель на него в оператор new: #include <new> Необходимо для использования синтаксиса размещения #include Fred.h Определение класса Fred void someCode() { char memory[sizeof(Fred)]; #1 void* place = memory; #2 Fred* f = new(place) Fred(); #3 Указатели f и place будут равны ... В строчке #1 создаётся массив из sizeof(Fred) байт, размер которого достаточен для хранения объекта Fred. В строчке #2 создаётся указатель place, который указывает на первый байт массива (опытные программисты на С наверняка заметят, что можно было и не создавать этот указатель; мы это сделали лишь чтобы код б1 более понятным). В строчке #3 фактически происходит только вызов конструктора Fred::Fred(). Указатель this в конструкторе Fred будет равен указателю place. Таким образом, возвращаемый указатель тоже будет равен place. Совет: Не используйте синтаксис размещения new, за исключением тех случаев, когда вам действительно нужно, чтобы объект б1 размещён в определённом месте в памяти. Например, если у вас есть аппаратный таймер, отображённый на определённый участок памяти, то вам может понадобиться поместить объект Clock по этому адресу. Опасно: Используя синтаксис размещения new вы берёте на себя всю ответственность за то, что передаваемый вами указатель указывает на достаточный для хранения объекта участок памяти с тем выравниванием (alignment), которое необходимо для вашего объекта. Ни компилятор, ни библиотека не будут проверять корректность ваших действий в этом случае. Если ваш класс Fred должен быть выровнен по четырёхбайтовой границе, но вы передали в new указатель на не выровненный участок памяти, у вас могут быть большие неприятности (если вы не знаете, что такое выравнивание (alignment), пожалуйста, не используйте синтаксис размещения new). Мы вас предупредили. Также на вас ложится вся ответственность по уничтожению размещённого объекта. Для этого вам необходимо явно вызвать деструктор: void someCode() char memory[sizeof(Fred)]; void* p = memory; Fred* f = new(p) Fred(); f->~Fred(); Явный вызов деструктора для размещённого объекта Это практически единственный случай, когда вам нужно явно вызывать деструктор. Когда я пишу деструктор, должен ли я явно вызывать деструкторы для объектов-членов моего класса? Нет. Никогда не надо явно вызывать деструктор (за исключением случая с синтаксисом размещения new. Деструктор класса (неявный, созданный компилятором, или явно описанный вами) автоматически вызывает деструкторы объектов-членов класса. Эти объекты уничтожаются в порядке обратном порядку их объявления в теле класса: class Member { public: ~Member(); ... class Fred { public: ~Fred(); ... private: Member x ; Member y ; Member z ; Fred::~Fred() Компилятор автоматически вызывает z .~Member() Компилятор автоматически вызывает y .~Member() Компилятор автоматически вызывает x .~Member() Когда я пишу деструктор производного класса, нужно ли мне явно вызывать деструктор предка? Нет. Никогда не надо явно вызывать деструктор (за исключением случая с синтаксисом размещения new). Деструктор производного класса (неявный, созданный компилятором, или явно описанный вами) автоматически вызывает деструкторы предков. Предки уничтожаются после уничтожения объектов-членов производного класса. В случае множественного наследования непосредственные предки класса уничтожаются в порядке обратном порядку их появления в списке наследования. class Member { public: ~Member(); ...
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |