Блог пользователя dmital

Автор dmital, 12 лет назад, По-русски

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

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

П.С. Да, я новичок, и, возможно, не знаю совершенно очевидных кому-то вещей. Вопрос гуглил, но ответа не нашел.

П.П.С. Посоветуйте книги типа этой, желательно, с примерами на С++.

Спасибо за внимание.

Теги c++, stl
  • Проголосовать: нравится
  • +12
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

От stl надо избавляться, если чувствуется, что программа по времени будет работать близко к пределу. Но обычно проблем не возникает(особенно когда сервер быстрый(например, здесь, на кодефорсес)).

»
12 лет назад, # |
  Проголосовать: нравится -6 Проголосовать: не нравится

При этом тормозят в основном vector и deque. А вот set и map обычно не сильно уступают(а иногда и выигрывают) у написанных своими руками сбалансированных деревьев.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    В ace.delos.com советуют избегать от vector как от чумы.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Ну если использование вектора заметно упрощает жизнь, и при этом TL стоит с запасом, то избавляться от него не стоит(чтобы избежать лишних багов).

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится +9 Проголосовать: не нравится

        Дело не только в багах но и том, что писать свои дин.массивы сравнительно долго.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +9 Проголосовать: не нравится

      Это от лени объяснять, как в разных случаях ими грамотно пользоваться и избегать проблем со скоростью.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Да, но все же зачастую, задачу можно решить без их использования. Заюзав, например, сортировку, которая между прочим отличная, плюс бинпоиск или хэшмапу.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Хэшмапа вроде как очень тормознутая, ее лучше руками писать.

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        Естесственно руками, но в среднем стлвская хэшмапа у меня работала быстрее, но не сильно.

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Это потому что ты писать хеш таблицы не умеешь. Stl-евская реализация тормозная. Скорость её можно существенно улучшить, если задать другую величину средней заполнености, но и в таком виде она остаётся тормозной.

          • »
            »
            »
            »
            »
            »
            12 лет назад, # ^ |
            Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

            Может, я что-то не понял. Но причем здесь мое умение писать хэштейбл? И вообще откуда такая инфа интересно?

            UPD: я говорил о map и unordered_map, т.е. я делал исключительно свое сравнение между этими структурами из стандартной библиотеки. О своих хэшмапах я ничего не упоминал.

            • »
              »
              »
              »
              »
              »
              »
              12 лет назад, # ^ |
              Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

              kraskevich:"Хэшмапа вроде как очень тормознутая, ее лучше руками писать."
              notime.sea:"Естесственно руками, но в среднем стлвская хэшмапа у меня работала быстрее, но не сильно."
              ...
              notime.sea:"О своих хэшмапах я ничего не упоминал."

              no comments

              "И вообще откуда такая инфа интересно?"
              какая инфа? попытаюсь угадать ваш вопрос, предположим он должен был быть "откуда информация о скорости работы Stlевской хешмапы?" — из личного опыта, давным давно я для себя потестировал эту структуру, дабы оценить её полезность для acm.
              Здесь и выше я говорю об stdext::hash_map ибо unordered_map есть только в C++11, а мы говорим об СП, где его использование не столь широко, и вообще я только сегодня узнал что есть такой класс. Не тестировал этот класс, но ставлю на то что рукописная реализация его также уделает. Дело в том что этот класс применим к более широкому классу задач чем наша самопальная хешмапа, которой не надо соответствовать каким-то правилам типа правильного удаления по константной ссылке на ключ. Нашей самопальной мапе не надо ресайзиться при заполнении, память под все элементы мы выделяем статически. В таких условиях самопальное всегда будет быстрее по определению.

              • »
                »
                »
                »
                »
                »
                »
                »
                12 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                Если я правильно понял, то от постоянного ресайза можно избавиться: http://cplusplus.com/reference/stl/unordered_set/reserve/

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  12 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

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

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Люблю подобные заявления, можете показать как и что вы измеряли?

        Я вот недавно сравнивал в GCC4.6 unordered_map и map на 10 миллионах случайных строк длины 10 и получилось, что unordered_map в 5-10 раз быстрее, как при заполнении таблицы, так и при чтении.

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

    Насколько я знаю, всё как раз наоборот. vector в STL работает практически с такой же скоростью что и обычный массив. Вообще если вы заранее объявите размер вектора, то уступит он массиву может 5% времени. А вот set и map. написанные умелыми руками, не только более подойдут для специализированных задач, но будут работать быстрее. Однако писать свой set и map долго и почти всегда не нужно. Совсем другое дело string. Более ужасной вещи чем string представить трудно. Он может есть памяти не в 2, а чуть ли не в 5 раз больше чем использует на самом деле. При этом работает он ОЧЕНЬ медленно. Вот это точно чума.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Ну если размер вектора известен заранее, то он в этом случае вообще не нужен. А если много push_back'ть, то получается раза в 1,5 — 2 медленнее, чем массив.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      вектор работает дольше массива — 100%, не знаю на сколько, то точно дольше

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      вы писали set быстрее стлевского? с map согласен, он ужасен, но вот обогнать set не могу уже давно...

    • »
      »
      »
      12 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

      Я использую массив крайне редко. В основном пользуюсь вектором. В это плане очень помогают конструкторы и функции assign и resize. Например: нужно считать массив из n элементов. Очень часто вижу такое:

      vector <int> a;
      int n;
      cin >> n;
      for (int i = 0; i < n; i++)
          {
              int x;
              cin >> x;
              a.push_back(x)
          }
      

      , что есть сильное замедление программы и памяти в худшем случае может уйти O(2*n). Я предпочитаю так:

      int n;
      cin >> n;
      vector <int> a(n); //vector <int> a(n, x);
                         // если надо заполнить вектор значением x
      for (int i = 0; i < n; i++)
         cin >> a[i];
      

      если же нужен вектор глобальный, то так: объявляю вектор за мэйном, а мэйне так:

      int n;
      cin >> n;
      a.resize(n);//a.assign(n, x);
      for (int i = 0; i < n; i++)
          cin >> a[i];
      

      Результат: я ни разу не получал ТЛ, связанный с вектором.

      • »
        »
        »
        »
        12 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится +1 Проголосовать: не нравится

        Вот как раз у меня есть вопрос на эту тему. Работает ли медленнее resize, чем передача размера в конструктор(в вашем первом варианте)? И еще один вопрос, уже по поводу assign. Какова скорость в сравнении с fill(iterator begin, iterator end, x)? Быстрее/Медленнее?

        P.S. Можно делать так: a.resize(n, x) (Создает вектор из n элементов и заполняет числом/строкой/etc x)

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Про второе значение в resize я не знал. А вот по поводу скорости resize и конструктора — не измерял, но когда заменял конструктор на resize разницы не чувствовал. А про fill(iterator begin, iterator end, x) я не слышал. Как я понял — это заполнение от begin() до end() иксами?

          • »
            »
            »
            »
            »
            »
            12 лет назад, # ^ |
            Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

            Да. Это в <algorithm>. Вот примеры использования:

            vector<int> a(n);
            fill(a.begin(), a.end(), x) //Заполнения от начала до конца иксами
            fill(a.begin(), a.begin() + m, a) //Заполнение от начала до m-ого элемента a-шками
            fill(a.begin() + k, a.begin() + l, b) //Заполнение от k-ого элемента по l-ый b-эшками
            
      • »
        »
        »
        »
        12 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится

        Результат: я ни разу не получал ТЛ, связанный с вектором.

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

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

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится +1 Проголосовать: не нравится

          Все таки ты знаешь только максимальный размер, который может понадобиться. А вектору довольно удобно указывать именно тот размер, который поступает на вход. Ну это мое субъективное мнение :)

          • »
            »
            »
            »
            »
            »
            12 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

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

            • »
              »
              »
              »
              »
              »
              »
              12 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Да. В общем можно юзать вектора, а если не заходит, то можно попробовать заменить на массивы :)

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          спасибо, приму к сведению.

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Во. Дельный совет, сам так делаю и проблем не знаю. Еще имеет смысл использовать reserve в тех случаях, когда размер массива точно не известен. Например, это подойдет для запихивания простых чисел на отрезке.

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

У меня есть классная книга про STL

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится +9 Проголосовать: не нравится

Я бы не рекомендовал использовать std::list. Основная причина это динамическое выделение памяти под каждый узел списка, что добавляет тормозов в зависимости от аллокатора (системного имею в виду, а не STLевского). Воторой негативный момент в динамической памяти это что она выделяется блоками, например в 32-х битных виндах эти блоки обычно по 16 байт, и даже если мы вызываем new для выделения памяти под структуру в 1 байт, у нас все равно выделится 16 байт. Кроме того организовать связный список руками не такая уж проблема. Особенно скорость списка критична когда нам нужна быстрая структура для доступа, и мы вместо map пишем свою хеш-мапу, ествественно нельзя здесь использовать тормознутые списки, надо руками писать свои.
Ну и для гиков аргументы:
1) юзая свои списки можно в одной структуре реализовать несколько списков, например я так поступаю с бором для ахо-корасик. Все переходы (вершина, буква) хрянятся в общей хеш-таблице, узлы из одной хеш-ячейки связаны между собой как связный список по полю next (цепочка для разруливания коллизий) также те же самые узлы связаны между собой в список по полю brother (список детей некоторого другого узла)
2) память можно выделить статически, типа TMyNode mem[MAX_NODES];
это даёт возможность убрать из структуры поле Id т.к. Id вычисляется по адресу: int GetId(TMyNode* node) { return node - mem; }

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится -14 Проголосовать: не нравится

    Я бы так сильно не бросался нападками на std::list для этого нужно привести свою реализацию и я могу хорошо раскритиковать твой код где всё гладко, а где плохо. Знаешь почему память выделяется блоками это сделано специально для оптимизации ведь для этого и создавалась страничная адресация, да ладно что тут говорить вернёмся к списку. list двунаправленный список то есть он жрёт больше памяти чем однонаправленный slist-список, но он быстрее работает по удалению и вставки узла где у 2-ух связного оценка в O(1) по сравнению с slist O(n)... Наверное у тебя каша в голове для каких реализаций применять ту или иную структуру данных, только без обид. Связные списки хороши тем что используют память эффективно без лишней памяти по сравнению с разряжёнными массивами и хэш-таблицами, например для создания ассоциативных структур можно выбирать использовать хэш-таблицу или BST-деревья, AVL-деревья или RB-деревья, ну да можно и декартовое дерево, а для линейных данных vector, deque, slist, list, queue, stack. Я как разработчик 3D-игр давно убедился в эффективности библиотеки STL почти никогда меня stl-контейнеры не подводили, для начала попробуй написать свою реализацию list для работы в боевых условиях где кол-во выборок зашкаливает. На счёт статических массивов ведь не всегда точно известно сколько будет входных данных или думаешь зря в языке С/С++ строки заканчиваются \0 — null terminate. Конечно статический массив работает быстрее динамического так как динамический массив теряет время на реаллокацию и копирование. Приведу немного прикладной пример, например вы разрабатываете векторный редактор и вы как разработчик не можете точно знать сколько объектов будет создавать пользователь и что на ум приходит какая структура данных, конечно динамический массив или связной список, вот как раз тут статический массив не подходит. И последнее ведь библиотека STL создавалась не для одного типа машин, теперь подумайте на досуге.
    P.S. Чем сложнее код, тем больше число ошибок.

    • »
      »
      »
      12 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +27 Проголосовать: не нравится

      Очень хочется верить в то што я не кармлю троля а указыаю уважаемому разработчику 3d-игр на ошибки в частности то что знаки припинания некто неотменял и текст без них читать очень сложно попробуй самостоятельно прочитать свой текст и осознать что ты имел виду может даже руский не твой радной язык но этого из профиля не понять

      В случае олимпиад все входные данные, параметры компилятора, тестирующие машины и прочие условия чётко ограничены и скорость работы стоит на первом месте перед читаемостью, поддержкой и всем прочим. На олимпиаде мне всё равно, что бывают little-endian и big-endian машины; я пишу код, который использует порядок байт и по очевидным причинам не будет работать на PowerPC. Мне неважно, что моей программе могут дать тест из строки длиной 2·105 символов, когда ограничения в два раза меньше — на нормальной олимпиаде (а их подавляющее число) виновато будет жюри, тест уберут и выполнят перетестирование.

      Но мне существенно мешают те 500 мс, которые моя программа теряет на выделении памяти блоками по 16 байт (а это сильно медленнее единовременного выделения массива на 16 МиБ) и двухкратное замедление из-за прыжков по памяти.

    • »
      »
      »
      12 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      Мои слова "Я бы не рекомендовал использовать std::list.", следует понимать как "Я бы не рекомендовал использовать в олимпиадном программировании std::list". Выше yeputons описал особенности применения списков в олимпиадном программировании.
      Даже на практике, часто бывает очень полезно дать MemoryPool списку или любой другой структуре данных использующей динамическое выделение памяти, это даст выигрыш в производительности, и не сильно усложнит код. Заявление про кашу в голове о структурах данных довольно резкое, и я бы не кидался такими заявлениями в адрес опытных олимпиадников. Многие школьники успешно занимающиеся олимпиадами бьют в этом отношении многих опытных бородатых разработчиков.
      ну и приведу простую реализацию, раз просили.

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

ну смотря на сколько использовать стл, если в случае с очередью ты запихиваешь <10^5 элементов, грубо говоря, не думаю что разница будет принципиальная с рукописной очередью, если же довольно много элементов, то однозначно стл-структура будет дольше работать

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

Как именно Вы компилировали и как именно меряли время?

В частности, не сыграл ли тут какой-то факт наподобие того, что в Visual Studio большинство STL-ных структур в Debug Mode проводят огромное количество не нужных для получения результата (но очень полезных с точки зрения контроля правильности!) дополнительных проверок, так что время может оказываться бОльшим в десятки раз, а иногда даже асимптотически (n2 против n log n); в Release mode все эти проверки отключаются, и получается вполне себе терпимое время работы, отличающееся от вылизанной низкоуровневой реализации не более чем в 1,1--1,5 раза.

UPD И ещё, если речь идёт о сдаче именно на информатиксе — можете назвать конкретную задачу и конкретное время сдачи; тут немало людей, у которых достаточно прав на информатиксе, чтоб посмотреть, в чём дело. Если оно конечно ещё надо...

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

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

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

    Благодарю всех отписавшихся за помощь.

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      Почитал код 32-27505 Дмитрий Талецкий 645. Lines 2012-08-31 15:20:12 GNU C++ Частичное решение 3 3 Подробнее

      По крайней мере в этой программе претензии к STL мимо кассы, проблема в алгоритме: он может добавлять одну и ту же клеточку в очередь по много-много раз (очень примерно — миллиарды раз для поля 20*20).

      Так что не надо было столь уверенно говорить о STL и надо было приводить свой код (например, через ideone.com) прямо в вопросе.

»
12 лет назад, # |
Rev. 3   Проголосовать: нравится +3 Проголосовать: не нравится

Если посмотреть как устроен queue и deque в STL-e, легко понять почему он медленней самописной очереди (под самописной очередью я понимаю зацикленный массив фиксированного размера).

Сразу пару замечаний: детали реализации могут отличаться в зависимости от компилятора, и они не оговорены стандартом. Причина почему сделано описанным ниже образом заключается в том, что deque должен быть динамическим, то есть никакого ограничения на количество элементов заранее нет, плюс требуется push/pop_back, push/pop_front и random_access за учетное O(1).

Так вот упрощенно stack, queue, deque устроены следющим образом -- это список корзин (назовем их a_1, ..., a_n). В каждой корзине лежит фиксированное количество элементов (B), которые ты хранишь в очереди. В любой момент времени, хранящиеся в deque данные -- это (a_i[start], ... a_i[B-1], a_{i+1}[0], ..., a_j[0], ..., a_j[end]). Как устроены операции более менее понятно. Единственный нетривиальный случай -- когда заполняются первая или последняя корзина, в таком случае выделают еще корзину и добавляют её в массив корзин. Сами корзины (то есть указатели на корзины) скорее всего лежат в веторе, или двустороннем векторе. Прочитать подробнее можно в исходниках stl: c++_include/bits/stl_deque.

Такая структура работает достаточно быстро и удовлетворяет всех указанным требованиям, плюс съедает небольшое количество дополнительной памяти. Но надо понимать, что доступ к произвольному элементу требует (1) операции вычисления адреса этого элемента и (2) приводит к большему количеству cache miss-ов, так как данные лежат по бакетам, которые в памяти могут находится далеко друг от друга.

Теперь про vector vs статический массив. С алгоритмической точки зрения заранее выделенный vector нужного размера не должен ничем уступать стат-массиву. Однако в практике олимпиадного программирования такое возможно. Причина, как мне кажется, в том, что все стат. массивы обычно заводятся на стеке (глобальные переменные), что безусловно дает некоторое ускорение.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Статические объекты (со static storage duration) выделяются не на стеке, а в специально отведённой области памяти, которая создаётся при запуске программы.

    Я проводил некоторые исследования по теме vector vs массив. Могу подтвердить, что в GCC операции доступа к элементам одинаковы в обоих случаях. Единственное различие — это необходимость одной лишней инструкции в случае vector, которая загружает адрес массива, хранящийся в объекте vector. Естественно, в случае цикла по вектору эту инструкцию не нужно повторять при каждой итерации, так что она почти не влияет на скорость выполнения.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +4 Проголосовать: не нравится

    Так вот упрощенно stack, queue, deque устроены следющим образом -- это список корзин

    deque да, а stack и queue — это адапторы. Не нравится deque? Передавай им другой контейнер.

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

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

    • a) использовать существенно больше памяти, чем статический массив такого же размера (из-за обеспечения амортизированного O(1) на push_back/pop_back)
    • b) намного медленнее работать из-за перевыделения памяти при увеличении размера.

    Когда же мы работаем с вектором, как со статическим массивом, то есть итерация/обращение по индексу, то наличие разницы по скорости будет зависеть от конкретной реализации stl и конкретного компилятора. Я видел очень много обсуждений (не связанных с олимпиадами), где рассматривались тормоза вектора по сравнению с массивом при итерациях с обращением по индексу. Большинства этих обсуждений не было бы, если бы во многих версиях Dinkum STL (это именно та STL, что идет вместе с Visual Studio) в релизной версии vector::operator[] не было бы проверки на выход за пределы вектора (!). А она там была, поэтому обращение по индексу к вектору даже в релизе было совсем не таким же легким, как обращение по индексу к массиву. И поэтому сравнивать их было бесполезно в таком виде, сравнивать нужно было итерацию по вектору с помощью итераторов.

    Так что в идеальном мире, где реализация вектора не содержит лишних телодвижений, где компилятор всегда сможет заинлайнить вызов operator[], скорость работы с вектором без изменения его размера не должна отличаться от скорости работы с массивом. В реальном мире может оказаться, что сравниться по скорости со статическим массивом может разве что итерация по вектору с помощью итератора.