C ++: удаление против свободного и производительности - PullRequest
26 голосов
/ 30 ноября 2008
  1. Рассмотрим:

    char *p=NULL;
    free(p) // or
    delete p;
    

    Что произойдет, если я использую free и delete на p?

  2. Если выполнение программы занимает много времени, скажем, 10 минут, есть ли способ сократить время ее выполнения до 5 минут?

Ответы [ 7 ]

61 голосов
/ 30 ноября 2008

Некоторые заметки о производительности new / delete и malloc / free:

malloc и free не вызывают конструктор и деконструктор соответственно. Это означает, что ваши классы не будут автоматически инициализированы или деинициализированы, что может быть плохо (например, неинициализированные указатели)! Это не имеет значения для типов данных POD, таких как char и double, так как у них на самом деле нет ctor.

new и delete do вызов конструктора и деконструктора. Это означает, что экземпляры вашего класса инициализируются и деинициализируются автоматически. Однако обычно наблюдается снижение производительности (по сравнению с простым распределением), но это к лучшему.

Я предлагаю оставаться в соответствии с использованием новых / malloc, если у вас нет причины (например, realloc). Таким образом, вы получаете меньше зависимостей, уменьшая размер кода и время загрузки (хотя только smidgin). Кроме того, вы не будете путать, освобождая что-то, выделенное с помощью new, или удаляя что-то, выделенное с помощью malloc. (Это, скорее всего, приведет к сбою!)

13 голосов
/ 30 ноября 2008

Ответ 1: и free(p), и delete p отлично работают с указателем NULL.

Ответ 2: Невозможно ответить, не видя медленных частей кода. Вы должны профилировать код! Если вы используете Linux, я предлагаю использовать Callgrind (часть Valgrind ), чтобы выяснить, какие части выполнения занимают больше всего времени.

10 голосов
/ 30 ноября 2008

Вопрос первый: ничего не случится.

Из текущего проекта ISO / IEC 14882 (или: C ++):

20.8.15 C Библиотека [c.malloc]

Содержимое [из <cstdlib>, то есть: где free живет,] такое же, как в стандартной библиотеке C [(см. Intro.refs)] заголовок <stdlib.h> со следующими изменениями: [ ничего, что влияет на этот ответ].

Итак, из ИСО / МЭК 9899: 1999 (или: C):

7.20.3.2 Функция free

Если [the] ptr [параметр] является нулевым указателем, никаких действий не происходит .

Снова из стандарта C ++, для информации о delete на этот раз:

3.7.4.2 Функции выделения ресурсов [basic.stc.dynamic.deallocation]

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

Смотри также:

4 голосов
/ 30 ноября 2008

Ничего не произойдет, если вы вызываете free с параметром NULL или удаляете с операндом NULL. Оба определены для принятия NULL и не выполнять никаких действий.

В коде C ++ можно изменить любое количество вещей, которые могут повлиять на скорость его выполнения. Часто наиболее полезными (в приблизительном порядке) являются:

  • Используйте хорошие алгоритмы. Это большая тема, но, например, я недавно вдвое сократил время выполнения кода, используя std :: vector вместо std :: list, в случае, когда элементы добавлялись и удалялись только в конце .
  • Избегайте повторения длинных вычислений.
  • Избегайте ненужного создания и копирования объектов (но все, что происходит менее 10 миллионов раз в минуту, не будет иметь существенного значения, если вы не обработаете что-то действительно большое , например, вектор из 10 миллионов) элементы).
  • Компиляция с оптимизацией.
  • Пометить часто используемые функции (опять же, все, что вызывалось более 100 миллионов раз за 10 минут работы) как встроенные.

Сказав это, divandconquer абсолютно прав - вы не можете эффективно ускорить свою программу, если не знаете, на что она тратит свое время. Иногда это можно угадать правильно, когда вы знаете, как работает код, а иногда это очень удивительно. Так что лучше в профиль. Даже если вы не можете профилировать код, чтобы точно определить, на что тратится время, если вы измерите, как повлияют ваши изменения, вы, в конце концов, сможете это выяснить.

2 голосов
/ 30 ноября 2008

Как уже отмечали другие, удаление (или освобождение) указателя NULL ничего не сделает. Однако, если вы выделили немного памяти, то использовать ли free () или delete, зависит от метода, который вы использовали для их выделения. Например, если вы использовали malloc () для выделения памяти, то вы должны освободить (), а если вы использовали new для выделения, то вы должны использовать delete. Однако будьте осторожны, чтобы не перепутать распределение памяти. Используйте один способ их выделения и освобождения.

По второму вопросу будет очень сложно обобщить, не увидев реальный код. Это должно быть принято на индивидуальной основе.

2 голосов
/ 30 ноября 2008

На вопрос 2:
Предыдущие ответы отличные. Но я просто хотел добавить кое-что о предварительной оптимизации. Предполагая, что программа средней сложности, правило 90/10 обычно применяется, то есть 90% времени выполнения тратится на 10% кода. «Оптимизированный» код часто труднее читать и поддерживать. Поэтому всегда сначала решайте проблемы, а затем смотрите, где находятся узкие места (профилирование - хороший инструмент).

1 голос
/ 01 декабря 2008

Хорошие ответы на все.

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

Правило 90/10 верно. По моему опыту, обычно есть несколько проблемных точек, и они обычно находятся на среднем уровне стека вызовов. Они часто вызваны использованием общих структур данных, но вы никогда не должны что-то исправлять, если не доказали, что это действительно проблема. Проблемы с производительностью удивительно непредсказуемы.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...