2016-08-05 4 views
0

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

Пусть у меня есть класс/структура:

class employee 
{ 
    //member variables 
    //member methods - getter/setters,etc 
} 

Теперь предположит, что я хочу работать с каждым сотрудником в массиве.

Подход 1:

for (loop on array of 10 employees) 
{ 
    employee emp(loop element); //using constructor of employee for initialization 
    //operate on the current loop element using emp 
} 

Таким образом, согласно моему пониманию, 10 объектов EMP будет получить созданы до finishes.Now петли, так как это не включает в себя динамическое распределение памяти, как только управление выходит из цикла , будут удалены все 10 объектов (& память, занятая 10, будет освобождена), или только последний объект будет удален (& память, занятая 9 объектами, не будет освобождена).

подход 2:

for (loop on array of 10 employees) 
{ 
    employee *emp=new employee(loop element); //using constructor of employee for initialization 
    //operate on the current loop element using emp 
    delete emp; 
    emp = nullptr; 
} 

Здесь находится под контролем программиста, поэтому мы можем освободить память, сами в каждой итерации цикла. Хотя это также вызовет частые выделения & освобождение памяти кучи & может привести к некоторому ухудшению ситуации, если цикл предназначен для огромного числа сотрудников.

Пожалуйста, помогите мне с запросом, упомянутым в подходе 1 &, пожалуйста, укажите, какой из приведенных выше подходов хорош. И если есть какой-либо подход к тому же?

ответ

0

Подход 1 будет выделять объект сотрудника в стек, что, безусловно, быстрее, чем использование динамического распределения памяти (кучи). На каждой итерации объект-сотрудник станет недоступен, поэтому его дескриптор будет вызываться каждый раз. Это хорошая вещь со стеком, автоматически «сбор мусора», когда вы покидаете область действия (см. Is a destructor called when an object goes out of scope?).

1

Подход 1 лучше, так как вы не должны полагаться на балансирование new с delete так что менее вероятно, утечка памяти: если ваш «работать на» кода были бросить исключение в подходе 2, то delete бы не. В подходе 1 деструктор будет вызываться, если исключение генерируется при распаке стека.

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

1

Я не уверен, что понимаю проблему. Если у меня есть цикл над объектами, и я не хочу изменять объект, я бы его не копировал. Я бы просто использовал ссылку const.

for(auto const& e: employees) { 
    // operate on e 
} 

Если объект изменяется, т.е. не константная функция член называется, я хотел бы использовать неконстантную ссылку

for(auto&& e: employees) { 
    // operate on e 
} 

В вашем примере, «временный» объект служащий либо стек - или выделено в виде кучи. В первом случае объект создается в стеке. Это означает, что компилятор просто увеличивает (или уменьшает) указатель стека к значению, в котором достаточно места в стеке, чтобы удерживать объект employee, а затем использует конструктор для его инициализации. Никакое распределение кучи не будет выполнено, и есть только один объект типа employee, живой плюс один из цикла. Срок службы заканчивается, когда область действия заканчивается. Ни в коем случае не будет десяти объектов в конце цикла.

Второй случай идентичен временам жизни w.r.t, но выделяет объекты в куче. Это намного медленнее, но при удалении объектов все время жизни одинаково. В этом случае я бы посоветовал использовать std::unique_ptr, так как он также является безопасным для вас и избавляет вас от ручного управления памятью. У вас есть утечка памяти, когда операционная часть генерирует исключение.

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