Во-первых, как отмечалось выше, если ваш компилятор не может оптимизировать метод size()
, поэтому он просто вызывается один раз или представляет собой не что иное, как одно чтение (без накладных расходов на вызов функции), тогда это повредит. *
Есть еще один эффект, о котором вы, возможно, захотите беспокоиться. Если ваш размер контейнера достаточно велик, то первый случай будет выполняться быстрее. Это потому, что, когда он достигает test[i].bar()
, test[i]
будет кэшироваться. Во втором случае с разделенными циклами кэш будет перегружен, поскольку для каждой функции test[i]
всегда нужно перезагружать.
Хуже того, если в вашем контейнере (std::vector
, я полагаю) есть так много элементов, что он не помещается в память, а некоторые из них должны храниться в подкачке на вашем диске, тогда разница будет Огромный, поскольку вы должны загружать вещи с диска дважды .
Однако есть еще одна заключительная вещь, которую вы должны учитывать: все это имеет значение только в том случае, если нет зависимости порядка между вызовами функций (в действительности, между различными объектами в контейнере). Потому что, если вы решите это, первый случай:
test[0].foo();
test[0].bar();
test[1].foo();
test[1].bar();
test[2].foo();
test[2].bar();
// ...
test[test.size()-1].foo();
test[test.size()-1].bar();
в то время как второй делает:
test[0].foo();
test[1].foo();
test[2].foo();
// ...
test[test.size()-1].foo();
test[0].bar();
test[1].bar();
test[2].bar();
// ...
test[test.size()-1].bar();
Так что, если ваш bar()
предполагает, что все foo()
запущены, вы сломаете его, если смените второй случай на первый. Аналогично, если bar()
предполагает, что foo()
не был запущен на более поздних объектах, то переход от второго случая к первому нарушит ваш код.
Так что будьте осторожны и документируйте, что вы делаете.