Для всех практических целей, при использовании таким образом, они имеют ту же скорость. Оператор вектора [] обычно реализован так [версия MSVC]:
const_reference operator[](size_type _Pos) const
{ // subscript nonmutable sequence
return (*(_Myfirst + _Pos));
}
... что совпадает с:
const_reference operator[](size_type _Pos) const
{ // subscript nonmutable sequence
return _Myfirst[_Pos];
}
Ваш тест в основном просто проверяет способность вашего компилятора встроить код, и, похоже, он делает это хорошо здесь.
Что касается объяснения различий, то любые ответы, которые вы получите, как правило, будут гипотетическими, не видя разборки. Это может быть связано с улучшенным кэшированием, регистры лучше используются в первом случае (попробуйте поменять местами порядок тестов и посмотрите, что произойдет) и т. Д. Стоит отметить, что доступ к памяти вектора будет осуществляться до того, как тест начнется с как он инициализирует все в T () в ctor.
К сожалению, мы не можем просто написать такие маленькие микротесты и сделать из них общие выводы. Раньше мы могли делать это еще до того, как системы и оптимизирующие компиляторы становились такими сложными, но теперь слишком много переменных задействовано, чтобы делать значимые выводы из чего-либо, кроме реальных тестов.
По этой же причине мы обычно ожидаем, что любой, кто серьезно относится к производительности, будет активно профилировать свой код, поскольку людям стало слишком сложно правильно определять узкие места в своем коде, за исключением очевидной алгоритмической неэффективности ( часто встречаются даже опытные программисты, которые гораздо лучше понимают ассемблер и архитектуру компьютера, чем я, неправильно понимая это, когда проверяю их гипотезы с помощью профилировщика).