для очень больших строк. В документации SGI контейнер
rope
описывается так:
Контейнер
rope
представляет собой масштабированную разновидность
string
: он предназначен для эффективного выполнения операций со строками в целом. Затраты времени на такие операции, как присваивание, конкатенация и выделение подстроки, практически не зависят от длины строки. В отличие от строк C, контейнер
rope
обеспечивает разумное представление
для очень длинных строк (например, содержимого буфера текстового редактора или сообщений электронной почты).
Во внутреннем представлении контейнер
rope
реализуется в виде дерева подстрок с подсчетом ссылок, при этом каждая строка хранится в виде массива
char
. Одна из интересных особенностей интерфейса
rope
заключается в том, что функции
begin
и
end
всегда возвращают тип
const_iterator
. Это сделано для предотвращения операций, изменяющих отдельные символы. Такие операции обходятся слишком дорого. Контейнер
rope
оптимизирован для операций с текстом в целом или большими фрагментами (присваивание, конкатенация и выделение подстроки); операции с отдельными символами выполняются неэффективно.
• Различные нестандартные объекты функций и адаптеры. Некоторые классы функторов из исходной реализации HP STL не вошли в Стандарт C++. Опытным мастерам старой школы больше всего не хватает функторов
select1st
и
select2nd
, чрезвычайно удобных при работе с контейнерами
map
и
multimap
. Функтор
select1st
возвращает первый компонент объекта
pair
, а функтор
select2nd
возвращает второй компонент объекта
pair
. Пример использования этих нестандартных шаблонов классов функторов:
map<int, string> m;
…
// Вывод всех ключей map в cout
transform(m.begin, m.end,
ostream_iterator<int>(cout, "\n"),
select1st<map<int, string>::value_type>);
// Создать вектор и скопировать в него
// все ассоциированные значения из map
vector<string> v;
transform(m.begin, m.end, back_inserter(v),
select2nd<map<int, string>::value_type>);
Как видите, функторы
select1st
и
select2nd
упрощают использование алгоритмов в ситуациях, где обычно приходится писать собственные циклы (см. совет 43). С другой стороны, вследствие нестандартности функторов вас могут обвинить в написании непереносимого и вдобавок плохо сопровождаемого кода (см. совет 47).
Настоящих фанатов STL это нисколько не волнует. Они считают, что отсутствие
select1st
и
select2nd
в Стандарте само по себе является вопиющей несправедливостью.
К числу нестандартных объектов функций, входящих в реализацию STL, также принадлежат объекты
identity
,
project1st
,
project2nd
,
compose1
и
compose2
. Информацию о них можно найти на сайте, хотя пример использования
compose2
приводился на с. 172 настоящей книги. Надеюсь, я убедил вас в том, что посещение web-сайта SGI принесет несомненную пользу.
Реализация библиотеки от SGI выходит за рамки STL. Первоначально ставилась цель разработки полной реализации стандартной библиотеки C++ за исключением компонентов, унаследованных из C (предполагается, что у вас в распоряжении уже имеется стандартная библиотека C). По этой причине с сайта SGI также стоит получить реализацию библиотеки потоков ввода-вывода C++. Как следует ожидать, эта реализация хорошо интегрируется с реализацией STL от SGI, но при этом по быстродействию она превосходит многие аналогичные реализации, поставляемые с компиляторами C++.
Сайт STLport
Главная отличительная особенность STLport заключается в том, что эта модифицированная версия реализации STL от SGI (включая потоки ввода-вывода и т. д.) была перенесена более чем на 20 компиляторов. STLport, как и библиотека SGI, распространяется бесплатно. Если ваш код должен работать сразу на нескольких платформах, вы избавите себя от множества хлопот, если возьмете за основу унифицированную реализацию STLport и будете использовать ее со всеми компиляторами.
Большинство изменений кода SGI в реализации STLport связано с улучшением переносимости, однако STLport является единственной известной мне реализацией, в которой предусмотрен «отладочный режим» для диагностики случаев неправильного использования STL — компилируемых, но приводящих к непредсказуемым последствиям во время работы программы. Например, в совете 30 распространенная ошибка записи за концом контейнера поясняется следующим примером:
int transmogrify(int х); // Функция вычисляет некое новое значение
// по переданному параметру х
vector<int> values;
… // Заполнение вектора values данными
vector<int> results;
transform(values.begin, // Попытка записи за концом results!
values.end, results.end, transmogrify);
Этот фрагмент компилируется, но во время выполнения работает непредсказуемо. Если вам повезет, проблемы возникнут при вызове
transform
, и отладка будет относительно элементарной. Гораздо хуже, если вызов
transform
испортит данные где-то в другом месте адресного пространства, но это обнаружится лишь позднее. В этом случае определение причины порчи данных становится задачей — как бы выразиться? — весьма нетривиальной.
Отладочный режим STLport значительно упрощает эту задачу. При выполнении приведенного выше вызова
transform
выдается следующее сообщение (предполагается, что реализация STLport установлена в каталоге C:\STLport):