2013-10-04 2 views
7

Какой метод быстрее и имеет меньше накладных расходов?очистка вектора или определение нового вектора, который быстрее

Метод 1:

void foo() { 
    std::vector<int> aVector; 
    for (int i = 0; i < 1000000; ++i) { 
    aVector.clear(); 
    aVector.push_back(i); 
    } 
} 

Метод 2:

void foo() { 
    for (int i = 0; i < 1000000; ++i) { 
    std::vector<int> aVector; 
    aVector.push_back(i); 
    } 
} 

Вы можете сказать, что пример не имеет смысла! Но это всего лишь фрагмент моего большого кода. Короче говоря, я хочу знать, это лучше

«создать вектор один раз и очистить его для использования»

или

«создать новый вектор каждый раз, когда»

UPDATE

Спасибо за предложения, я испытал оба и вот результаты

Способ 1:

$ time ./test1 

real 0m0.044s 
user 0m0.042s 
sys  0m0.002s 

Способ 2:

$ time ./test2 

real 0m0.601s 
user 0m0.599s 
sys  0m0.002s 

Очистка вектора лучше. Возможно, это поможет кому-то еще :)

+1

«очистка вектора или определение нового вектора, который быстрее» - сравнивайте его с тем, что вы будете знать. Нет общего утверждения, которое можно было бы сделать, поскольку это зависит от многих деталей, связанных с платформой и реализацией. –

+0

Согласитесь, но я хочу знать, как g ++ генерирует оптимизированный код для методов. Какой из них лучше для компилятора? – mahmood

+2

Я бы ожидал, что метод 'clear' будет быстрее, если есть какая-либо разница. –

ответ

6

Скорее всего, clear() будет быстрее, так как вы сохраните память, выделенную для предыдущих push_back() s, в вектор, что уменьшает необходимость в распределении.

Также у вас есть 1 вызов конструктора и 1 вызов деструктора за цикл.

Это все игнорирование того, что вы можете оптимизировать для компилятора, с этим кодом.

+0

+1 Что я собирался писать. –

0

Для создания пустого вектора очень мало накладных расходов. Чтобы GROW вектор большого размера потенциально довольно дорогостоящий, так как он каждый раз удваивается по размеру - так что вектор ввода 1М будет иметь 15-20 "копий" из текущего содержимого.

Для простых базовых типов, таких как int, накладные расходы на создание объекта и уничтожение объекта - «ничего», но для любого более сложного объекта вам нужно будет учитывать конструкцию и разрушение объекта, который часто существенно больше, чем «поместить объект в вектор» и «удалить его из вектора». Другими словами, конструктор и деструктор для каждого объекта имеет значение.

Для КАЖДОГО, «который быстрее X или Y», вам действительно нужно ориентироваться на обстоятельства, которые вы хотите понять, если только ОЧЕНЬ очевидно, что он явно быстрее другого (например, «линейный поиск» или «двоичный поиск») элементов X ", где линейный поиск пропорционален X, а бинарный поиск - log2 (x)).

Кроме того, я немного запутался в вашем примере. Сохранение элемента ONE в векторе довольно громоздко и справедливо немного накладных расходов над int x = i;. Предполагаю, вы на самом деле не имеете в виду это как ориентир. Другими словами, ваше конкретное сравнение не очень справедливо, потому что четкое построение векторов 1M - это больше работы, чем построение ONE-вектора и его заполнение и очистка 1M раз.Тем не менее, если вы сделали свой тест что-то вроде этого:

void foo() { 
    for (int i = 0; i < 1000; ++i) { 
    std::vector<int> aVector; 
    for(j = 0; j < 1000; j++) 
    { 
     aVector.push_back(i); 
    } 
    } 
} 

[и соответствующее изменение в другой код], я думаю, что результаты будут довольно похожи.

+0

std :: vector динамически выделяет память. Когда динамические процедуры распределения называются очень часто (как в этом примере), они превращаются в большие узкие места, даже если данные не имеют конструкторов. Поскольку clear() обычно не сокращает внутренние данные, вызов clear будет быстрее. – SigTerm

+0

@SigTerm: Да, но вы также можете использовать 'aVector.resize (1000)', чтобы избежать этого выделения. Но, как я уже сказал, это зависит от того, что хранится в векторе. –

+0

Если целью является 'push_back', то' aVector.reserve (1000) 'будет более точным. –

Смежные вопросы