Справедливости ради стоит отметить, что сразу же за положением об эквивалентности однотипных распределителей памяти в Стандарт включен следующий текст: «...Авторам реализаций рекомендуется создавать библиотеки, которые... поддерживают неэквивалентные распределители. В таких реализациях... семантика контейнеров и алгоритмов для неэквивалентных экземпляров распределителей определяется самой реализацией».

Трогательное проявление заботы, однако пользователю STL, рассматривающему возможность создания нестандартного распределителя с состоянием, это не дает практически ничего. Этим положением можно воспользоваться только в том случае, если вы уверены в том, что используемая реализация STL поддерживает неэквивалентные распределители, готовы потратить время на углубленное изучение документации, чтобы узнать, подходит ли вам «определяемое самой реализацией» поведение неэквивалентных распределителей, и вас не беспокоят проблемы с переносом кода в реализации STL, в которых эта возможность может отсутствовать. Короче говоря, это положение (для особо любознательных — абзац 5 раздела 20.1.5) лишь выражает некие благие намерения по поводу будущего распределителей. До тех пор пока эти благие намерения не воплотятся в жизнь, программисты, желающие обеспечить переносимость своих программ, должны ограничиваться распределителями без состояния.

Выше уже говорилось о том, что распределители обладают определенным сходством с оператором new — они тоже занимаются выделением физической памяти, но имеют другой интерфейс. Чтобы убедиться в этом, достаточно рассмотреть объявления стандартных форм operator new и allocator::allocate:

void* operator new(size_t bytes);

pointer allocator::allocate(size_type numObjects);

// Напоминаю: pointer - определение типа.

//практически всегда эквивалентное Т*

В обоих случаях передается параметр, определяющий объем выделяемой памяти, но в случае с оператором new указывается конкретный объем в байтах, а в случае с allocator:: allocate указывается количество объектов Т, размещаемых в памяти. Например, на платформе, где sizeof (int)=4, при выделении памяти для одного числа int оператору new передается число 4, а allocatort>::allocate — число 1. Для оператора new параметр относится к типу size_t, а для функции allocate — к типу allocator::size_type, В обоих случаях это целочисленная величина без знака, причем allocator::size_type обычно является простым определением типа для size_t. В этом несоответствии нет ничего страшного, однако разные правила передачи параметров оператору new и allocator:: allocate усложняют использование готовых пользовательских версий new в разработке нестандартных распределителей.

Перейти на страницу:

Все книги серии Библиотека программиста

Похожие книги