Мегаобучалка Главная | О нас | Обратная связь


Предпочитайте операции с диапазонами операциям с отдельными элементами



2016-01-26 388 Обсуждений (0)
Предпочитайте операции с диапазонами операциям с отдельными элементами 0.00 из 5.00 0 оценок




 

 

Резюме

 

При добавлении элементов в контейнер лучше использовать операции с диапазонами (т.е. функцию insert, которая получает пару итераторов), а не последовательность вызовов функции для вставки одного элемента. Вызов функции для диапазона обычно проще написать, легче читать, и он более эффективен, чем явный цикл (см. также рекомендацию 84).

 

Обсуждение

 

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

To же самое можно сказать и об операциях "повторить n раз", например, о конструкторе vector, который получает количество повторений и значение.

 

Примеры

 

Пример 1. vector::insert . Пусть вам надо добавить n элементов в vector v. Многократный вызов v.insert(position,x) может привести к неоднократному перераспределению памяти, когда вектор v имеет недостаточно места для размещения нового элемента. Что еще хуже, вставка каждого отдельного элемента имеет линейное время работы, поскольку она должна перенести ряд элементов, чтобы освободить требуемую позицию для вставляемого элемента, а это приводит к тому, что вставка n элементов при помощи последовательных вызовов имеет квадратичное время работы! Конечно, избежать проблемы множественного перераспределения памяти можно при помощи вызова reserve, но это не снизит количества перемещений элементов и квадратичное время работы такого алгоритма. Быстрее и проще ясно сказать, что вам надо: v.insert(position,first,last), где first и last — итераторы, определяющие диапазон элементов, которые должны быть добавлены в v. (Если first и last — входные итераторы, то возможности определить размер диапазона перед его действительным проходом нет, так что вектору v может потребоваться многократное перераспределение памяти; тем не менее, версия для вставки диапазона все равно скорее всего будет более производительной, чем вставка отдельных элементов.)

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

 

Ссылки

 

[Meyers01] §5 • [Stroustrup00] §16.3.8

 

Используйте подходящие идиомы для реального уменьшения емкости контейнера и удаления элементов

 

 

Резюме

 

Для того чтобы действительно избавиться от излишней емкости контейнера, воспользуйтесь трюком с использованием обмена, а для реального удаления элементов из контейнера — идиомой erase-remove.

 

Обсуждение

 

Некоторые контейнеры (например, vector, string, deque) могут иметь "лишнюю" емкость, которая больше не будет использоваться. Хотя стандартная библиотека C++ не предоставляет гарантированного способа для удаления излишней емкости, следующая идиома на практике оказывается вполне работоспособной:

container<T>(c).swap(c); // Идиома "горячей посадки" для

// устранения излишней емкости

// контейнера

Для того чтобы полностью опустошить c, удалив все элементы и убрав всю емкость, идиома должна выглядеть следующим образом:

container<T>().swap(c); // Идиома для удаления всего

// содержимого и емкости

Кроме того, обычно для новичков в программировании с использованием STL оказывается сюрпризом то, что алгоритм remove в действительности не удаляет элементы из контейнера. Понятно, что данный алгоритм на это не способен — ведь алгоритм работает только с диапазоном итераторов и не может ничего реально удалить из контейнера без вызова функции-члена контейнера, обычно erase. Удаление сводится к перемещению элементов, которые должны быть "удалены", и возврату итератора, указывающего на элемент, следующий за последним неудаленным. Для реального удаления элементов из контейнера после вызова remove следует вызвать erase — воспользоваться идиомой erase-remove. Например, для реального удаления всех элементов, равных value, из контейнера с, можно написать:

c.erase(remove(c.begin(), c.end(), value), c.end());

Если контейнер имеет собственную версию remove или remove_if, желательно использовать именно ее.

 

Исключения

 

Описанная идиома "горячей усадки" не работает с реализациями std::string с копированием при записи. Обычно работает вызов s.reserve(0) или такой трюк, как string(s.begin(), s.end()).swap(s);, в котором использован конструктор на основе двух итераторов. На практике эти методы обычно работают и устраняют излишнюю емкость. (Было бы еще лучше, чтобы реализации std::string не использовали такой устаревший метод оптимизации, как копирование при записи; см. [Sutter02].)

 

Ссылки

 

[Josuttis99] §6.2.1 • [Meyers01] §17, §32, §44 • [Sutter00] §7 • [Sutter02] §7, §16

 

 

STL: алгоритмы

 

Предпочитайте алгоритмы циклам.

— Бьярн Страуструп (Bjarne Stroustrup),

[Stroustrup00] §18.12

 

Алгоритмы представляют собой циклы — только они лучше циклов. Алгоритмы — это "шаблоны" циклов, с добавлением дополнительной семантики по сравнению с простыми for и do. Конечно, начав использовать алгоритмы, вы начнете использовать и функциональные объекты и предикаты; корректно пишите их и широко используйте в своих программах.

В этом разделе мы считаем наиболее значимой рекомендацию 83 — "Используйте отладочную реализацию STL".

 



2016-01-26 388 Обсуждений (0)
Предпочитайте операции с диапазонами операциям с отдельными элементами 0.00 из 5.00 0 оценок









Обсуждение в статье: Предпочитайте операции с диапазонами операциям с отдельными элементами

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Как выбрать специалиста по управлению гостиницей: Понятно, что управление гостиницей невозможно без специальных знаний. Соответственно, важна квалификация...
Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ...
Личность ребенка как объект и субъект в образовательной технологии: В настоящее время в России идет становление новой системы образования, ориентированного на вхождение...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (388)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.007 сек.)