C ++ утечка памяти, но я удалил объект [duplicate]

Вот оптимизированная реализация:

  public static final Comparator & lt; CharSequence & gt;  VERSION_ORDER = new Comparator & lt; CharSequence & gt; () {@Override public int compare (CharSequence lhs, CharSequence rhs) {int ll = lhs.length (), rl = rhs.length (), lv = 0, rv = 0, li =  0, ri = 0;  char c;  do {lv = rv = 0;  while (-ll & gt; = 0) {c = lhs.charAt (li ++);  если (c & lt; '0' || c & gt; '9') break;  lv = lv * 10 + c - '0';  } while (-rl & gt; = 0) {c = rhs.charAt (ri ++);  если (c & lt; '0' || c & gt; '9') break;  rv = rv * 10 + c - '0';  }} while (lv == rv & amp; & amp; (ll & gt; = 0 || rl & gt; = 0));  return lv - rv;  }};   

Результат:

  "0.1" - "1.0" = -1 "1.0" - "1.0" = 0 "1.0" - "1.0.0  "= 0" 10 "-" 1.0 "= 9" 3.7.6 "-" 3.7.11 "= -5" foobar "-" 1.0 "= -1  
5
задан Unihedron 10 August 2014 в 12:32
поделиться

10 ответов

delete неявно вызывает деструктор, вам не нужно (точнее: не должно) называть его напрямую.

Деструктор никогда не освободит память, занятую объектом (она может находиться в стеке, а не в куче, и объект не знает, но деструктор удалит любую память, выделенную компонентами объекта.

Чтобы освободить память объекта выделенного в куче, вы должны называть delete.

Когда вы пишете свой собственный класс, C ++ предоставит деструктор по умолчанию , чтобы освободить память, выделенную объектами компонента (например, a QString, который является членом вашего класса), но если вы явно выделяете память (или другие ресурсы) в своем конструкторе, обязательно укажите деструктор, который будет явно освобождать эти ресурсы.

Другое общее правило относительно ваших собственных классов: если вы отмечаете какие-либо методы virtual, ваш деструктор должен быть virtual, а также (даже если вы полагаетесь на деструктор по умолчанию), так что правильный деструктор вызывается для любых классов, полученных из ваших.

13
ответ дан Tony the Pony 16 August 2018 в 05:33
поделиться

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

4
ответ дан Amardeep AC9MF 16 August 2018 в 05:33
поделиться

Обычно вы никогда не хотите явно вызвать деструктор. Просто используйте delete.

4
ответ дан Carl Norum 16 August 2018 в 05:33
поделиться

Я не предпочитаю никого.

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

Явным delete является, возможно, законным способом уничтожения объекта, динамически созданного с помощью выражения new, но в большинстве приложений он не должен быть ненужным код, поскольку он сигнализирует место, где могут возникать потенциальные несоответствия между новым и удаленным, и областями с потенциальными проблемами безопасности исключений.

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

{
    // ...
    Object object( ... );

} // object destructor run, however this block is exited.

Если есть какая-то причина, что это не может быть необходимо (например, у объекта есть чрезмерный статический размер ) или его продолжительность жизни не может быть сопоставлена ​​с определенной областью, тогда обычно для управления временем жизни объектов должен использоваться какой-то умный указатель. Самый простой интеллектуальный указатель, который доступен в стандартном C ++, - std::auto_ptr, который может использоваться для объектов с динамическим распределением блоков, но имеет «удивительное» поведение при копировании и присваивании. Что-то вроде tr1::shared_ptr (или boost::shared_ptr) являются общими альтернативами, в которых требуется совместное владение.

{
    std::auto_ptr<Object> object(new Object(...));
    // ...
} // *object destructor run, however this block is exited.
7
ответ дан CB Bailey 16 August 2018 в 05:33
поделиться
  • 1
    +1 для упоминания опасностей ручного управления жизненным циклом, хотя я смиренно предлагаю изменить пример с auto_ptr на shared_ptr, чтобы не поощрять кого-либо, незнакомого с его тонкостями, использовать auto_ptr. – Niklas 3 June 2010 в 20:34

Вызов delete вызовет деструктор, а затем освободит память.

Вызвать деструктор явно вызовет только деструктор, а не освободит память.

Поэтому вы должны почти всегда вызов delete: за исключением случаев, когда вы хотите вызвать деструктор без освобождения памяти, например потому что вы построили объект с помощью размещения new .

4
ответ дан ChrisW 16 August 2018 в 05:33
поделиться

Используйте delete. Он вызывает объекты destructor , а затем освобождает выделенную память.

Кроме того, это не деконструктор, а деструктор.

4
ответ дан Costantino Rupert 16 August 2018 в 05:33
поделиться

Вы никогда не должны называть деструктора самостоятельно. delete вызовет его для вас

2
ответ дан Philippe Leybaert 16 August 2018 в 05:33
поделиться
  • 1
    Сделайте это «почти никогда». – user 3 June 2010 в 19:27
  • 2
    Если вы это сделаете, вы должны спросить себя, не является ли ваш дизайн неправильным – Philippe Leybaert 3 June 2010 в 19:57
  • 3
    @Philippe Вызов деструктора напрямую используется для уничтожения объектов, которые были созданы с использованием «размещения нового». – ChrisW 3 June 2010 в 20:30
  • 4
    Тогда вам лучше использовать компилятор, который поддерживает размещение delete . – Philippe Leybaert 3 June 2010 в 21:04
  • 5
    @Philippe: нет выражения удаления места размещения в отличие от нового, у которого есть необязательная форма размещения. Вы можете определить форму размещения operator delete, но это не уничтожает объекты, оно вызывается, когда оно соответствует operator new в новом выражении, и конструкция объекта завершается сбоем после того, как распределение памяти успешно отменяет выделенную необработанную память. Если новое выражение места размещения успешно завершено, то правильным способом уничтожения объекта является явный вызов деструктора, за которым следует соответствующее освобождение (если применимо). – CB Bailey 3 June 2010 в 22:20

Вы должны использовать delete

http://www.parashift.com/c++-faq-lite/dtors.html

1
ответ дан Cade Roux 16 August 2018 в 05:33
поделиться

Что-то еще, чтобы рассмотреть:

, поскольку delete вызывает деструктор внутри себя, это ошибка для обоих, т. е. вызов деструктора, а затем удаление. Итак, следующий код:

Foo* px = new Foo;
// …
px->~Foo();
delete px;

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

2
ответ дан Konrad Rudolph 16 August 2018 в 05:33
поделиться

Когда вы используете динамическое выделение памяти для создания объекта в это время, вы можете использовать оператор delete для уничтожения / удаления объекта, но когда вы не используете DMA в это время, пытаетесь удалить объект, используя команду delete, вызывается ошибка. Один из способов справиться с этой ситуацией - написать свой собственный деструктор в явном виде и вызвать деструктор, используя объект для его уничтожения.

0
ответ дан Spiderman 16 August 2018 в 05:33
поделиться