Разница не в производительности вектора по сравнению с динамическим массивом, а в количестве обращений к памяти, которые вы выполняете.
По сути, в векторном тесте вы снова получаете доступ к кэшированной памяти, а в версии массива - нет. Вы платите цену за кеширование векторной версии в любом случае.
В векторном тесте вы выделяете динамическую память для массива, но оставляете ее нетронутой, при этом память никогда не трогается, нет ошибок страницы из-за этой операции. Вектор создается, инициализируется, и затем второй проход будет обращаться к уже кэшированным данным (если размер соответствует кешу, если нет, он не будет в кеше, но в обеих версиях будут понесены одинаковые затраты).
С другой стороны, при тестировании массива векторный конструктор инициализирует элементов, и это означает, что в случае, если вы пытаетесь профилировать поведение массива, содержимое вектора перебирается и элементы массива пройдены. Удвойте количество обращений к памяти, ошибок страниц и памяти, используемой приложением.
Вы можете попробовать изменить код так, чтобы динамическое распределение выполнялось так:
int * intArray = new int[ numInts ](); // note extra ()
Который инициализирует значение всего массива, или вы инициализируете содержимое массива иначе. Результаты запуска этой модифицированной версии теста должны быть похожими.