Функции размещения и освобождения

Во всех приведенных примерах память рассматривалась как нечто данное.Но, рядовая функция общего предназначения для рассредотачивания свободнойпамяти оказывается до удивления наименее действенной, чем функция размещенияспециального предназначения. Вырожденным случаем таких функций можносчитать приведенный пример с размещением в "нескончаемой" памяти ис пустой функцией освобождения. В библиотеке могут быть болеесодержательные функции размещения, и бывает, что Функции размещения и освобождения с их помощьюудается удвоить скорость выполнения программки. Но до этого, чем пытатьсяс их помощью улучшить программку, запустите для нее профилировщик,чтоб выявить затратные расходы, связанные с выделением памяти. В разделах $$5.5.6 и $$6.7 было показано как при помощи определенияфункций X::operator new() и X::operator delete() можно использоватьфункцию размещения Функции размещения и освобождения для объектов класса X. Тут есть определеннаятрудность. Для 2-ух классов X и Y функции размещения могут бытьнастолько схожими, что лучше иметь одну такую функцию.Другими словами, лучше иметь в библиотеке таковой класс, которыйпредоставляет функции размещения и освобождения, применимые для размещенияобъектов данного класса. Если таковой класс есть, то функции Функции размещения и освобождения размещенияи освобождения для данного класса получаются за счет привязки к немуобщих функций размещения и освобождения: class X { static Pool my_pool; // ... public: // ... void* operator new(size_t) { return my_pool.alloc(); } void operator delete(void* p) { my_pool.free(p); } }; Pool X::my_pool(sizeof(X)); При помощи класса Pool Функции размещения и освобождения память распределяется блоками 1-го размера.В приведенном примере объект my_pool отводит память блокамиразмером sizeof(X). Составляется описание класса X и употребляется Pool с учетом оптимизациискорости программки и компактности представления. Направьте внимание,что размер выделяемых блоков памяти является для класса "интегрированным",потому задающий размер параметр функции X::operator new() неиспользуется Функции размещения и освобождения. Употребляется вариант функции X::operator delete()без параметра. Если класс Y является производным класса X, иsizeof(Y)>sizeof(X), то для класса Y должны быть свои функцииразмещения и освобождения. Наследование функций класса X приведетк катастрофе. К счастью, задать такие функции для Y до боли просто. Класс Pool предоставляет связанный Функции размещения и освобождения перечень частей требуемогоразмера. Элементы выделяются из блока памяти фиксированного размераи при необходимости запрашиваются новые блоки памяти. Элементыгруппируются большенными блоками, чтоб минимизировать число обращенийза памятью к функции размещения общего предназначения. До того времени покане будет уничтожен сам объект PooL, память никогда не возвращаетсяфункции размещения общего предназначения. Приведем описание класса Pool Функции размещения и освобождения: class Pool { struct Link { Link* next; } const unsigned esize; Link* head; Pool(Pool&); // защита от копирования void operator= (Pool&); // защита от копирования void grow(); public: Pool(unsigned n); ~Pool(); void* alloc(); void free(void* b); }; inline void* Pool::alloc() { if (head==0) grow(); Link* p = head; head = p->next; return p Функции размещения и освобождения; } inline void Pool::free(void* b) { Link* p = (Link*) b; p->next = head; head = p; } Приведенные описания разумно поместить в заголовочный файл Pool.h.Последующие определения могут находиться в любом месте программке изавершают наш пример. Объект Pool должен инициализироватьсяконструктором: Pool::Pool(unsigned sz) : esize(sz) { head = 0; } Функция Pool Функции размещения и освобождения::grow() будет связывать все элементы в перечень квантовсвободной памяти head, образуя из их новый блок. Определенияостальных функций-членов оставлены в качестве упражнений 5 и 6 в$$13.11. void Pool::grow() { const int overhead = 12; const int chunk_size = 8*1024-overhead; const int nelem = (chunk_size-esize)/esize; char* start = new char[chunk_size]; char* last Функции размещения и освобождения = &start[(nelem-1)*esize]; for (char* p = start; pnext = ((Link*)p)+1; ((Link*)last)->next = 0; head = (Link*)start; }

Упражнения

1. (*3) Окончите определения функций-членов класса Type_info.2. (*3) Предложите такую структуру объекта Type_info, чтоб функция Type_info::get_info() стала излишней, и перепишите с учетом этого функции-члены Type_info.3. (*2.5) Как наглядно Функции размещения и освобождения вы можете записать примеры с Dialog_box, не используя макроопределения (также расширения языка)? Как наглядно вам получится записать их, используя расширения языка?4. (*4) Обследуйте две обширно всераспространенные библиотеки. Систематизируйте все библиотечные классы, разбив их на: определенные типы, абстрактные типы, узловые классы, управляющие классы и интерфейсные классы. Употребляются ли абстрактные узловые классы Функции размещения и освобождения и определенные узловые классы? Можно ли предложить более подходящее разбиение классов этих библиотек? Употребляется ли широкий интерфейс? Какие имеются средства динамической инфы о типе (если они есть)? Какова стратегия управления памятью?5. (*3) Обусловьте шаблонный вариант класса Pool из $$13.10.3. Пусть размер выделяемого элемента памяти будет параметром шаблона типа Функции размещения и освобождения, а не конструктора.6. (*2.5) Усовершенствуйте шаблон типа Pool из предшествующего упражнения так, чтоб некие элементы располагались во время работы конструктора. Сформулируйте в чем будет неувязка переносимости, если использовать Pool с типом частей char, покажите как ее убрать.7. (*3) Если ваша версия С++ прямо не поддерживает динамические запросы о типе, обратитесь к собственной основной Функции размещения и освобождения библиотеке. Реализован ли там механизм динамических запросов о типе? Если это так, задайте операции из $$13.5 как надстройку над этим механизмом.8. (*2.5) Обусловьте таковой строковый класс, в каком нет никакого динамического контроля, и 2-ой производный от него строковый класс, который только проводит динамический контроль и обращается к первому. Укажите плюсы Функции размещения и освобождения и минусы такового решения по сопоставлению с решением,в каком делается выборочный динамический контроль, сравните с подходом, использующим инварианты, как было предложено в $$12.2.7.1. Как можно кооперировать эти подходы?9. (*4) Обусловьте класс Storable как абстрактный базисный класс с виртуальными функциями writeout() и readin(). Для простоты допустим, что для задания подходящего Функции размещения и освобождения адресного места довольно строчки знаков. При помощи класса Storable реализуйте обмен объектами с диском. Проверьте его на объектах нескольких классов по собственному усмотрению.10.(*4) Обусловьте базисный класс Persistent с операциями save() и nosave(), который будет инспектировать, что деструктор сделал объект в определенной памяти. Какие еще полезные операции можно предложить? Проверьте Функции размещения и освобождения класс Persistent на нескольких классах по собственному выбору. Является ли класс Persistent узловым классом, определенным либо абстрактным типом? Аргументируйте ответ.11.(*3) Составьте только описание класса stack, который реализует стек при помощи операций create() (сделать стек), delete() (убить стек), push() (записать в стек) и pop() (читать из стека). Используйте только статические члены Функции размещения и освобождения. Для привязки и обозначения стеков обусловьте класс id. Гарантируйте, что юзер сумеет копировать объекты stack::id, но не сумеет работать с ними другим методом. Сравните это определение стека с классом stack из $$8.2.12.(*3) Составьте описание класса stack, который является абстрактным типом ($$13.3). Предложите две разные реализации для интерфейса, данного stack. Напишите маленькую программку Функции размещения и освобождения, работающую с этими классами. Сравните это решение с классами, определяющими стек, из предшествующего упражнения и из $$8.2.13.(*3) Составьте такое описание класса stack, для которого можно в динамике поменять реализацию. Подсказка: "Всякую задачку можно решить, введя еще одну косвенность".14.(*3.5) Обусловьте класс Oper, содержащий идентификатор (некого подходящего типа) и операцию (некий Функции размещения и освобождения указатель на функцию). Обусловьте класс cat_object, содержащий перечень объектов Oper и объект типа void*. Задайте в классе cat_object операции: add_oper(), которая добавляет объект к списку; remove_oper(id), которая удаляет из перечня объект Oper c идентификатором id; operator() (id,arg), которая вызывает функцию из объекта Oper c Функции размещения и освобождения идентификатором id. Реализуйте при помощи класса cat_object стек объектов Oper. Напишите маленькую программку, работающую с этими классами.15.(*3) Обусловьте шаблон типа Object, служащий базисным классом для cat_object. При помощи Object реализуйте стек для объектов класса String. Напишите маленькую программку, использующую этот шаблон типа.16.(*3) Обусловьте вариант класса Object Функции размещения и освобождения под именованием Class, в каком объекты с схожим идентификатором имеют общий перечень операций. Напишите маленькую программку, использующую этот шаблон типа.17.(*3) Обусловьте шаблон типа Stack, который задает обычный и надежный интерфейс со стеком, реализуемым объектом шаблона типа Object. Сравните это определение стека с классами, задающими стек, из прошлых упражнений Функции размещения и освобождения. Напишите маленькую программку, использующую этот шаблон типа. Воззваний с начала месяца: 168, Last-modified: Fri, 22 Jan 1999 15:04:52 GMT Оцените этот текст: Не читал 10 9 8 7 6 5 4 3 2 1 Прогноз


funkcii-nauki-doklad.html
funkcii-nejrologii.html
funkcii-neverbalnogo-obsheniya.html