Здравствуйте, alex_public, Вы писали:
_>Тут на самом деле не всё так просто — надо чтобы компилятор мог гарантированно видеть неизменность переменной "a" внутри цикла. Например в C++ компилятор проводит эту оптимизацию для любых пользовательских типов без всяких модификаторов чистоты. Однако при этом в некоторых специфических случаях она не срабатывает, т.к. компилятор видит потенциальную возможность изменения переменной (хотя на самом деле никаких изменений естественно нет).
Основной инструмент, которым пользуется компилятор C++ — это инлайнинг.
А дальше — строим SSA-форму, в которой видно, что и где изменяется, и что остаётся инвариантом. _>Так что лучше сразу писать for(int i=0, е=a.GetLength(); i<е; i++), ну или использовать range for, которые транслируется (во всяком случае в C++) как раз в такую конструкцию.
Для кого лучше? Например, на C# такой код для встроенных массивов — явная пессимизация. Потому что JIT умеет распознавать паттерн i<a.Count и устраняет проверки границ. А паттерн i<e требует значительно более длинного пути для доказательства невыхода за границы, поэтому проверки будут оставлены. _>P.S. Если вдруг кто-то думает, что оптимизация выше — это какая то непринципиальная ерунда с экономией пары процессорных тиков, то это совсем не так. Например если мы всё же используем запись цикла в первом варианте и оптимизация с a.GetLength не пройдёт, то это автоматически заблокирует нам автовекторизацию этого цикла. А это уже может быть реальным провалом в быстродействие в десятки раз.
Ну вот в том-то и дело: декларация a.GetLength() как pure означает, что она не меняет мир — значит и a остаётся неизменной, поэтому можно оптимизировать всё.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.