Шаг 215.
Библиотека STL.
Итераторы STL. Проблема увеличения и уменьшения итераторов в векторах

    На этом шаге мы рассмотрим одну особенность использования операции увеличения/уменьшения итераторов.

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

  std::vector<int> coll;
  .   .   .   .   .
  // Сортировка, начиная со второго элемента 
  // - НЕПЕРЕНОСИМАЯ версия 
  if (coll.size() > 1) {
    sort(++coll.begin(), coll.end()); 
  }

    Обычно компиляция строки с вызовом sort() завершается неудачей, но если заменить вектор деком, компиляция пройдет нормально. Иногда программа компилируется даже для векторов - это зависит от реализации класса vector.

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

  std::vector<int> coll;
  .   .   .   .   .
  // Сортировка, начиная со второго элемента 
  // - ПЕРЕНОСИМАЯ версия 
  if (coll.size() > 1) {
    std::vector<int>::iterator beg = coll .begin(); 
    sort (++coll.beg, coll.end()); 
  }

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

    Со следующего шага мы начнем рассматривать вспомогательные функции итераторов.




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