Анимация
JavaScript
|
Главная Библионтека > Рекомендация Следует четко представлять, к каким реальным расходам памяти приводит использование различных видов контейнеров и стратегии распределения динамической памяти. Задача 22, Новый взгляд на new. Часть 1: многоликий оператор new Сложность: 4 Любой класс, предоставляющий собственный оператор new или new[], должен также обеспечить соответствующие версии обычного оператора new, размещающего new и new, не генерирующего исключений. В противном случае у пользователей вашего класса могут возникнуть ненужные проблемы. Вопрос ДЛЯ новичка 1. Какие три варианта оператора new описаны в стандарте С++? Вопрос для профессионала 2. Что такое оператор new, специфичный для класса, и как им следует пользоваться? Опишите, в каких случаях вы должны быть особо осторожны при предоставлении собственных, специфичных для класса операторов new и delete. 3. Какой именно оператор new вызывается в приведенном далее коде в строках, пронумерованных от 1 до 4? class Base { public: static void* operator new(std::si2e t, const FastMemoryA); class Derived : public Base { ... Derived* pl = new Derived; 1 Derived* p2 = new (std::nothrow) Derived; 2 void* p3 = /* некоторая область памяти, достаточная для размещения Derived */ ; new (рЗ) Derived; 3 FastMemory f; Derived* p4 = new (f) Derived; 4 Решение в этой и следующей задачах я хочу сформулировать и обосновать два основных совета. • Любой класс, предоставляющий собствснный оператор new или new[], должен также обеспечить соответствующие версии обычного оператора new, размещающего new и new, не генерирующего исключений. В противном случае у пользователей вашего класса могут возникнуть ненужные проблемы. • Избегайте использования new(nothrow) и убедитесь, что, когда вы проверяете отказ new, вы действительно проверяете именно то, что хотите проверить. Советы могут показаться неожиданными, поэтому давайте детально их проанализируем. Для простоты я не упоминаю отдельно оператор new для массивов, но все сказанное об операторе new для одного объекта, относится и к нему. Размещающий, обычный и не генерирующий исключений оператор new 1. Какие три варианта оператора new описаны в стандарте С++? В стандарте С++ описаны три варианта оператора new и разрешено произвольное количество дополнительных перегрузок. Одним полезным видом этого оператора является размещающий new, который строит объект в имеющейся области памяти, без выделения нового пространства. Например: пример 22-1(а): использование размещающего new выделение достаточного количества памяти void* р = ::operator new( sizeof(Т) ); new(p)T; создание объекта Т по адресу р, вероятно, вызовом ::operator new(std::size t, void*) throwQ Стандарт также предоставляет "обычный старый new", который не получает никаких дополнительных параметров и не генерирует исключений (nothrow new). И иже представлен полный список перегруженных операторов new из стандарта С+ + . перегрузки оператора new в стандарте языка (имеются соответствующие версии и для new[]): void* ::operator new(std::size .t size) throw(std::bad alloc); обычный старый оператор new Использование: new т void* ::operator new(std::size t size, const std::nothrow t&) throwC); Оператор new, не генерирующий исключений использование: new (std::nothrow) т void* ::operator new(std::size t size, void* Размещающий оператор new использование: new (ptr) T ptr) throwO; Программа может заменить все, кроме последнего, операторы new на свои собственные версии. Все эти стандартные функции находятся в глобальной области действия, а не в пространстве имен std. Табл. 22.1 дает краткие характеристики стандартных версий new. Таблица 22.1. Сравнение стандартных версий оператора new
После выгюлнения оператора new вызывается конструктор объекта, и, конечно, этот конструктор может вызвать сбой -- но в данном случае нас это не волнует. Сейчас нас интересует только вопрос о сбое в самом операторе new. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 [ 44 ] 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |