Положение повторно используемой переменной для цикла - PullRequest
0 голосов
/ 27 июля 2011

Каковы плюсы / минусы использования метода 1 против метода 2?

Метод 1:

for ( std::vector<MyObject*>::iterator it = my_objects.begin(); it != my_objects.end(); ++it )
{
    Vector2 temp_position = (*it)->GetPosition();
    // do something...
}

Метод 2:

Vector2 temp_position; // I do NOT need scope for this object outside of the loop.
for ( std::vector<MyObject*>::iterator it = my_objects.begin(); it != my_objects.end(); ++it )
{
    temp_position = (*it)->GetPosition();
    // do something...
}

Теоретически, метод 2 будет иметь лучшую производительность, чем метод 1, потому что переменную temp_position не нужно будет заново создавать каждый раз через цикл. Однако я помню, что читал, что компиляторы оптимизируют их так, чтобы они были одинаковыми.

Метод 1 лучше в том, что temp_position не имеет ненужных возможностей.

Ответы [ 2 ]

2 голосов
/ 27 июля 2011

Если мы игнорируем любые оптимизации, выполняемые компилятором, между функциями, вызываемыми каждой версией, есть конкретное различие.

В методе 1, поскольку вы создаете вектор внутри цикла, его конструктор будет вызываться один раз (в частности, его конструктор копирования), а его деструктор будет вызываться один раз для каждой итерации цикла. Таким образом, приблизительная стоимость составляет N вызовов конструктора копирования + N вызовов деструктора.

В методе 2, поскольку вектор уже существует в цикле for, вместо этого будет вызываться его оператор присваивания копии. Таким образом, его конструктор вызывается один раз, его деструктор вызывается один раз, а его оператор присваивания копии вызывается N раз. Примерная стоимость - 1 вызов конструктора копирования + 1 вызов деструктора + N вызовов оператора назначения копирования.

В итоге они примерно одинаковы с точки зрения объема работы. Каждый вызов оператора присваивания копии требует выделения одного массива и освобождения другого; с другой стороны, вызов конструктора копирования выделяет один массив, а деструктор освобождает один.

Я бы предпочел метод 1 просто потому, что он более точно отражает то, что вы пытаетесь сказать - вектор действительно временный и не должен существовать за рамками цикла.

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

«Преждевременная оптимизация - корень всего зла».- Этьен де Мартель

Аминь.Однако я на секунду переставлю свой ореол и скажу, что даже если компилятор, вероятно, оптимизирует этот цикл и, возможно, даже развернет его полностью, стоимость размещения в стеке по сравнению со всеми другими копиями и размещением, которые вы там делаете, не имеет значения.

Я бы написал этот цикл, как показано ниже, даже если компилятор, вероятно, все еще справится с этим и сделает все, что пожелает, в конце дня.

const std::vector<MyObject*>::const_iterator end(my_objects.cend());
for (std::vector<MyObject*>::const_iterator it(my_objects.cbegin()); it != end; ++it)
{
    Vector2 temp_position((*it)->GetPosition());
    // do something...
}
...