Шаг 101.
Библиотека STL.
Использование нескольких интервалов

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

    Некоторые алгоритмы работают сразу с несколькими интервалами. Обычно в таких случаях задаются начало и конец только одного интервала, а для остальных интервалов задается только начало. Конечная позиция других интервалов определяется по количеству элементов в первом интервале. Например, следующий вызов equal() поэлементно сравнивает все содержимое коллекции coll1 с элементами соll2, начиная с первого:

  if (equal (coll1.begin(), coll1.end(), 
      coll2.begin()) {
    .    .    .    .
  }

    Таким образом, количество элементов coll2, сравниваемых с элементами coll1, косвенно определяется количеством элементов в coll1.

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

    Рассмотрим следующую программу:

#include <iostream> 
#include <vector> 
#include <list>
#include <algorithm> 

using namespace std;

int main()
{
  list<int> coll1;
  vector<int> coll2;
  // Вставка элементов со значениями от 1 до 9 
  for (int i=1; i<=9; ++i) { 
    coll1.push_back(i);
  }
  // ОШИБКА ВРЕМЕНИ ВЫПОЛНЕНИЯ:
  // - перезапись несуществующих элементов в приемнике
  copy (coll1.begin(), coll1.end(),   // Источник
    coll2.begin());  //  Приемник
  // .    .    .
}

    В приведенном примере вызывается алгоритм copy(), который просто копирует все элементы первого интервала во второй (приемный) интервал. Как обычно, для первого интервала определяются обе границы, а для второго - только начало. Но данный алгоритм производит перезапись элементов вместо вставки, поэтому он требует, чтобы количество элементов в приемном интервале было достаточным для перезаписи. Если элементов не хватит (как в приведенном примере), последствия будут непредсказуемыми. На практике это часто означает перезапись данных, находящихся в памяти после coll2.end(). Если повезет, произойдет сбой программы; по крайней мере, вы будете знать, что случилось что-то не то. Впрочем, вы можете упростить себе жизнь и воспользоваться безопасной версией STL, в которой неопределенное поведение автоматически приводит к выполнению некоторой процедуры обработки ошибок.

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

    На следующем шаге мы закончим изучение этого вопроса.




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