У меня есть класс, объявленный в prob.h
таким образом:
struct A_s{
int a, b;
}
class A_c{
private:
std::vector<A_s> vec_of_A_s;
public:
int vec_of_A_s_size() const{return static_cast<int>(vec_of_A_s.size());}
}
С A_c A;//A is an object of class A_c
где-то еще в моей реализации .cpp
файл, у меня есть следующая строка:
for(int i = 0; i < A.vec_of_A_s_size(); i++) {...//do loop stuff}
Я ЗНАЮ от дизайна моей программы, что A.vec_of_A_s_size()
является инвариантным для цикла. Тем не менее, я действительно хочу избежать следующего (это громоздко):
int sz = A.vec_of_A_s_size();
for(int i = 0; i < sz; i++) {...//do loop stuff}
Могу ли я в достаточной мере и последовательно полагаться на компилятор, который не будет оценивать сборка выпуска с включенной оптимизацией (-O2) vec_of_A_s.size()
каждый раз?
Вот что я уже пробовал вместе со своими вопросами:
(1) (Пожалуйста, см. Редактирование обновления ниже) Даже с отладочной сборкой, с опциями -fPIC -fno-strict-aliasing -fexceptions -g -std=c++14
, глядя на вывод дизассемблера, vec_of_A_s.size()
оценивается только один раз. Однако будет ли компилятор делать эту оптимизацию надежно последовательно? Есть ли известные исключения? Частично причина моего скептицизма и потребности в уверенности вытекает из следующего вопроса (2).
(2) Я посмотрел на связанный вопрос о SO: Проблема производительности для вектора :: размер () в цикле. Вопрос там напрямую оценивает размер вектора в цикле следующим образом:
for(int i = 0; i < vec_of_A_s.size(); i++) {...//do loop stuff}
В моем случае, вектор не доступен напрямую. Это частный член A_c
и его размер может быть доступен только через функцию-член A.vec_of_A_s_size()
, Таким образом, существует дополнительный уровень косвенности / перенаправления, который должен происходить внутри цикла for. Ответы в этой теме позволяют предположить, что компилятор действительно оптимизирует инвариант цикла. Но в случае (как выше), когда размер вектора не является прямо и публично доступным, будет ли компилятор надежно гарантировать оптимизацию инварианта цикла?
(3) В других смежных вопросах по таким вопросам, общий ответ, кажется, для профилирования программы. Если и когда я выполняю профилирование, что именно я должен искать, чтобы проверить эту конкретную оптимизацию? Этот код является частью большего кода числового анализа, и это определенно НЕ текущее узкое место. Тем не менее, было бы неплохо узнать, как это можно проверить в профилировщике. Извиняюсь, если этот вопрос (3) слишком широк. Я относительно новичок в профилировании. Но позволяют ли профилировщики профилировать одну функцию, скажем, функцию, которая содержит for
цикл выше? Таким образом, я могу точно знать, где находится узкое место, так как оно относится к этой функции.
Изменить обновление:
На (1) НЕ верно, что отладочная сборка с указанными параметрами компилятора оптимизирует инвариант цикла. Я был неправ. При более глубоком копании оказывается, что функция действительно вызывается дважды.
Если ваш цикл вызывает неконстантный метод для вектора, то я бы с уверенностью сказал, что все ставки выключены.
Если вы вызываете только const-методы для вектора, тогда вы можете надеяться на оптимизацию, но поскольку стандарт не требует их, вы не можете винить компилятор в том, что он не сделал оптимизацию, которая может показаться вам очевидной,
Учитывая, что вы можете объявить более одной переменной в цикле for, если они одного типа, ввод sz в цикл кажется очевидной вещью. Или вы можете запустить цикл в обратном направлении?
Других решений пока нет …