Концепция управления жизненным циклом ресурсов (в данном случае — мьютексов) при помощи специализированных классов вроде Lock
vector
...
{// Создание нового блока
Lock
vector
if (first5 != v.end()) {
*first5 - 0:
}
}// Закрытие блока с автоматическим
// освобождением мьютекса
Поскольку мьютекс контейнера освобождается в деструкторе Lock,
важно обеспечить уничтожение Lock сразу же после освобождения мьютекса. Для этого мы создаем новый блок, в котором определяется объект Lock, и закрываем его, как только надобность в мьютексе отпадает. На первый взгляд кажется, что вызовreleaseMutexFor
попросту заменен необходимостью закрыть блок, но это не совсем так. Если мы забудем создать новый блок для Lock, мьютекс все равно будет освобожден, но это может произойти позднее положенного момента — при выходе из внешнего блока. Если забыть о вызове releaseMutexFor
Более того, решение, основанное на классе Lock,
лучше защищено от исключений. С++ гарантирует уничтожение локальных объектов при возникновении исключения, поэтому Lock освободит мьютекс, даже если исключение произойдет при использовании объекта Lock. При использовании парных вызововgetMutexFo
getMutexFor
releaseMutexFor
.Исключения и управление ресурсами важны, но данный совет посвящен другой теме — потоковой безопасности в STL. Как говорилось выше, вы можете
Контейнеры vector и string
Все контейнеры STL по-своему полезны, однако большинство программистов С++ работает с vector
и string чаще, чем с их собратьями, и это вполне понятно. Ведь контейнеры vector и string разрабатывались как замена массивов, а массивы настолько полезны и удобны, что встречаются во всех коммерческих языках программирования от COBOL до Java.В этой главе контейнеры vector
и string рассматриваются с нескольких точек зрения. Сначала мы разберемся, чем они превосходят классические массивы STL, затем рассмотрим пути повышения быстродействия vector и string, познакомимся с различными вариантами реализации string, изучим способы передачи string и vector функциям API, принимающим данные в формате С. Далее будет показано, как избежать лишних операций выделения памяти. Глава завершается анализом поучительной аномалии, vectorСовет 13. Используйте vector и string вместо динамических массивов
Принимая решение о динамическом выделении памяти оператором new,
вы берете на себя ряд обязательств.1.Выделенная память в дальнейшем должна быть освобождена оператором delete.
Вызов new без последующего delete приводит к утечке ресурсов.2.Освобождение должно выполняться соответствующей формой оператора delete.
Одиночный объект освобождается простым вызовом delete, а для массивов требуется форма delete []. Ошибка в выборе формы delete приводит к непредсказуемым последствиям. На одних платформах программа «зависает» во время выполнения, а на других она продолжает работать с ошибками, приводящими к утечке ресурсов и порче содержимого памяти.3. Оператор delete для освобождаемого объекта должен вызываться ровно один раз. Повторное освобождение памяти также приводит к непредсказуемым последствиям.
Итак, динамическое выделение памяти сопряжено с немалой ответственностью, и я не понимаю, зачем брать на себя лишние обязательства. При использовании vector и string необходимость в динамическом выделении памяти возникает значительно реже.