Вход/Регистрация
Эффективное использование STL
вернуться

Мейерс Скотт

Шрифт:

Более того, решение, основанное на классе

Lock
, лучше защищено от исключений. C++ гарантирует уничтожение локальных объектов при возникновении исключения, поэтому
Lock
освободит мьютекс, даже если исключение произойдет при использовании объекта
Lock
. При использовании парных вызовов
getMutexFor/releaseMutexFor
мьютекс не будет освобожден, если исключение происходит после вызова
getMutexFor
, но перед вызовом
releaseMutexFor
.

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

Контейнеры vector и string

Все контейнеры STL по-своему полезны, однако большинство программистов C++ работает с

vector
и string чаще, чем с их собратьями, и это вполне понятно. Ведь контейнеры
vector
и
string
разрабатывались как замена массивов, а массивы настолько полезны и удобны, что встречаются во всех коммерческих языках программирования от COBOL до Java.

В этой главе контейнеры

vector
и
string
рассматриваются с нескольких точек зрения. Сначала мы разберемся, чем они превосходят классические массивы STL, затем рассмотрим пути повышения быстродействия
vector
и
string
, познакомимся с различными вариантами реализации
string
, изучим способы передачи
string
и
vector
функциям API, принимающим данные в формате C. Далее будет показано, как избежать лишних операций выделения памяти. Глава завершается анализом поучительной аномалии,
vector<bool>
.

Совет 13. Используйте vector и string вместо динамических массивов

Принимая решение о динамическом выделении памяти оператором

new
, вы берете на себя ряд обязательств.

1. Выделенная память в дальнейшем должна быть освобождена оператором

delete
. Вызов
new
без последующего
delete
приводит к утечке ресурсов.

2. Освобождение должно выполняться соответствующей формой оператора

delete
. Одиночный объект освобождается простым вызовом
delete
, а для массивов требуется форма
delete[]
. Ошибка в выборе формы
delete
приводит к непредсказуемым последствиям. На одних платформах программа «зависает» во время выполнения, а на других она продолжает работать с ошибками, приводящими к утечке ресурсов и порче содержимого памяти.

3. Оператор

delete
для освобождаемого объекта должен вызываться ровно один раз. Повторное освобождение памяти также приводит к непредсказуемым последствиям.

Итак, динамическое выделение памяти сопряжено с немалой ответственностью, и я не понимаю, зачем брать на себя лишние обязательства. При использовании

vector
и
string
необходимость в динамическом выделении памяти возникает значительно реже.

Каждый раз, когда вы готовы прибегнуть к динамическому выделению памяти под массив (то есть собираетесь включить в программу строку вида «

new T[…]
»), подумайте, нельзя ли вместо этого воспользоваться
vector
или
string
. Как правило,
string
используется в том случае, если
T
является символьным типом, а
vector
— во всех остальных случаях. Впрочем, позднее мы рассмотрим ситуацию, когда выбор
vector<char>
выгладит вполне разумно. Контейнеры
vector
и
string
избавляют программиста от хлопот, о которых говорилось выше, поскольку они самостоятельно управляют своей памятью. Занимаемая ими память расширяется по мере добавления новых элементов, а при уничтожении
vector
или
string
деструктор автоматически уничтожает элементы контейнера и освобождает память, в которой они находятся.

Кроме того,

vector
и
string
входят в семейство последовательных контейнеров STL, поэтому в вашем распоряжении оказывается весь арсенал алгоритмов STL, работающих с этими контейнерами. Впрочем, алгоритмы STL могут использоваться и с массивами, однако у массивов отсутствуют удобные функции
begin
,
end
,
size
и т. п., а также вложенные определения типов (
iterator, reverse_iterator, value_type
и т. д.), а указатели
char*
вряд ли могут сравниться со специализированными функциями контейнера
string
. Чем больше работаешь с STL, тем меньше энтузиазма вызывают встроенные массивы.

Если вас беспокоит судьба унаследованного кода, работающего с массивами, не волнуйтесь и смело используйте

vector
и
string
. В совете 16 показано, как легко организовать передачу содержимого
vector
и
string
функциям C, работающим с массивами, поэтому интеграция с унаследованным кодом обычно обходится без затруднений.

Честно говоря, мне приходит в голову лишь одна возможная проблема при замене динамических массивов контейнерами

vector/string
, причем она относится только к
string
. Многие реализации
string
основаны на подсчете ссылок (совет 15), что позволяет избавиться от лишних выделений памяти и копирования символов, а также во многих случаях ускоряет работу контейнера. Оптимизация
string
на основе подсчета ссылок была сочтена настолько важной, что Комитет по стандартизации C++ специально разрешил ее использование.

Впрочем, оптимизация нередко оборачивается «пессимизацией». При использовании

string
с подсчетом ссылок в многопоточной среде время, сэкономленное на выделении памяти и копировании, может оказаться ничтожно малым по сравнению со временем, затраченным на синхронизацию доступа (за подробностями обращайтесь к статье Саттера «Optimizations That Aren't (In a Multithreaded World)» [20]). Таким образом, при использовании
string
с подсчетом ссылок в многопоточной среде желательно следить за проблемами быстродействия, обусловленными поддержкой потоковой безопасности.

  • Читать дальше
  • 1
  • ...
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: