Шаг 119.
Библиотека STL.
Элементы контейнеров. Семантика значений и ссылочная семантика

    На этом шаге мы рассмотрим использование указателей в контейнерах STL.

    Все контейнеры создают внутренние копии своих элементов и возвращают эти копии. Следовательно, элементы контейнера равны, но не идентичны объектам, заносимым в контейнер. При модификации объектов, являющихся элементами контейнера, вы модифицируете копию, а не исходный объект.

    Копирование значений означает, что контейнеры STL поддерживают семантику значений. Они содержат значения вставляемых объектов, а не сами объекты. Но на практике также возникает необходимость в ссылочной семантике, при которой контейнеры содержат ссылки на объекты, являющиеся их элементами.

    Принятый в STL подход, то есть поддержка только семантики значений, имеет свои положительные и отрицательные стороны. К достоинствам такого подхода относятся:

    Недостатки:

    На практике нужны оба подхода: копии, независимые от исходных данных (семантика значений), и копии, ссылающиеся на исходные данные и изменяющиеся вместе с ними (ссылочная семантика). К сожалению, стандартная библиотека C++ не поддерживает ссылочную семантику. Впрочем, ее можно реализовать в контексте семантики значений.

    Наиболее очевидная реализация ссылочной семантики основана иа использовании указателей как элементов контейнеров. Тем не менее обычным указателям присущи хорошо известные недостатки. Например, объект, на который ссылается указатель, оказывается несуществующим, или операция сравнения работает не так, как предполагалось, потому что вместо объектов сравниваются указатели на них. Следовательно, при использовании обычных указателей в элементах контейнеров нужно действовать очень осторожно.

    Более разумное решение основано на применении умных указателей - объектов, поддерживающих интерфейс указателей, но выполняющих дополнительную внутреннюю проверку или другие операции. Но здесь возникает важный вопрос: насколько умными должны быть эти указатели? В стандартную библиотеку C++ входит класс умного указателя auto_ptr, который на первый взгляд мог бы пригодиться. К сожалению, этот класс не подходит, поскольку не удовлетворяет одному из основных требований к элементам контейнеров, а именно: после копирования или присваивания объектов класса auto_ptr оригинал и копия не эквивалентны. Исходный объект auto_ptr изменяется, потому что значение передается, а не копируется. На практике это означает, что сортировка и даже простой вывод элементов контейнера может привести к их уничтожению. Следовательно, объекты auto_ptr не должны использоваться как элементы контейнеров (в системе C++, соответствующей стандарту, такие попытки приводят к ошибкам компиляции).

    Чтобы реализовать ссылочную семантику для контейнеров STL, вам придется написать собственный класс умного указателя. Но будьте внимательны: испольэование умного указателя с подсчетом ссылок (умного указателя, который автоматически уничтожает связанный объект при уничтожении последней ссылки на него) вызовет немало проблем. Например, при прямом доступе к элементам возможна модификация их значений, пока они находятся в контейнере. В ассоциативном контейнере это приведет к нарушению порядка следования элементов, а это недопустимо.

    Со следующего шага мы начнем рассматривать ошибки и исключения внутри STL.




Предыдущий шаг Содержание Следующий шаг