Являются ли container.end () и container.size () встроенными? - PullRequest
2 голосов
/ 11 апреля 2011

Обычно я вступаю в дискуссию с другими и не могу подтвердить поведение - если встроены функции container.end () и container.size (). Например, если у нас есть цикл for как таковой:

for (vector<int>::iterator it=v.begin(); it!=v.end(); ++it) {
   //...
} 

for (size_t k=0; k < v.size(); ++k) {
   //...
}

В указанных выше случаях будут ли функции v.end () и v.size () вызываться повторно или

  1. компилятор встроит эти функции
  2. Будет ли временная переменная создана компилятором
  3. Влияют ли параметры оптимизации O1..3 на поведение в g ++?

Ответы [ 3 ]

2 голосов
/ 11 апреля 2011

Все функции шаблона по определению являются встроенными функциями.Компилятор может сделать их вызываемыми функциями, особенно если это компиляция в режиме отладки, но наиболее вероятный результат - это встроенный код.

Возможно, но маловероятно, что временная переменная будет создана автоматически.Как компилятор определяет, повлияет ли на возвращаемые значения v.end () или v.size () код в цикле?Я подозреваю, что большинство не беспокоится, хотя у меня нет никаких доказательств в любом случае.

1 голос
/ 02 июля 2011

Даже если функции встроены, вы не можете рассчитывать на то, что компилятор правильно оптимизирует цикл, если вложенный код достаточно велик / сложен. Это потому, что семантически , вы, вероятно, не ожидаете, что значение end() будет меняться на каждой итерации цикла, поэтому его следует вычислять только один раз и. Однако компилятор может быть не в состоянии дать такую ​​гарантию, основываясь на соображениях псевдонимов и других условиях отказа в оптимизаторе. Если - как и другие авторы ответили - вы предварительно вычислили end() и сохранили его в переменной, компилятор с меньшей вероятностью запутается.

Например:

typedef std::vector<int> intvec;
intvec v = external_function();
for (intvec::const_iterator vi = v.begin(); vi != v.end(); ++vi) {
    call_external_function(v, *vi);
}

С точки зрения компилятора, call_external_function() может изменить размер вектора. Если вы знаете, что это не может произойти, вы должны сообщить компилятору так:

for (intvec::const_iterator vi = v.begin(), ve = v.end(); vi != ve; ++vi) {
    call_external_function(v, *vi);
}
0 голосов
/ 11 апреля 2011

Несмотря на то, что функции шаблона встроены, трудно сказать, что компилятор обеспечит ту же степень оптимизации, которая нам нужна.Можно использовать следующие методы.

Хранить v.end() во временной vEnd:

for(vector<TYPE>::iterator it = v.begin(), vEnd = v.end(); it != vEnd; it++) {}

Выполнить цикл в обратном порядке:

for (size_t k = v.size() - 1; k != (size_t)(-1) ; --k) { }
...