Способность компилятора выполнить оптимизацию зависит (как минимум) от задействованных типов.Например, если begin
и end
являются итераторами списка, а a
является списком, а end
является итератором в конце a
, то это бесконечный цикл (пока не завершитсяпамять происходит).Компилятор не может выполнить «оптимизацию», если он меняет смысл программы.Предположительно, это не меняет смысла программы, иначе вы бы не задали вопрос, но все же компилятор должен как-то исключить такую возможность, например, отслеживая значение end
, где бы оно ни было установлено.В некоторых случаях это может быть очевидно для вас, но компилятор не может доказать.
И наоборот, если begin
и end
являются векторными итераторами, то на практике они являются либо указателями, либотонкая обертка вокруг одного.Тогда компилятор вполне может увидеть, что их значения никогда не изменятся в цикле, и, следовательно, их расстояние никогда не изменится, и выполнить оптимизацию.Даже если оптимизация не выполняется, distance
дешево для векторных итераторов.Таким образом, оптимизация может быть не столь значимой в любом случае в этом случае.
И наоборот, проверка реализации векторного итератора может теоретически включать в себя код, чтобы увидеть, был ли вектор перераспределен с момента его выбора (и, следовательно, итератор больше не действителен).Этот факт может изменить в цикле, поэтому, если std::distance
косвенно вызывает эту проверку, то в этой реализации ее невозможно поднять.Не то чтобы вы обычно комбинировали проверочный итератор с оптимизацией, но это возможно.
Как всегда, оптимизация зависит от реализации.Если вам действительно важно, вам нужно взглянуть на код, генерируемый компилятором (ами), который вам небезразличен.
А для вашего второго фрагмента некоторые люди предпочитают этот стиль:
for (size_t i = 0, dist = std::distance(begin, end); i < dist; ++i) {
a.push_back(i);
}
Он основан на одинаковых типах в сравнении, но избегает помещения dist
в окружающую область, где это не обязательно.