Зачем вам писать что-то подобное? (намеренно не используя delete [] в массиве)
Я иногда сталкивался с подобным кодом - я подозреваю, что создатель/боялся, что удаление таблицы приведет к переходу по таблице и "эффективности затрат" (что imho не будет сделано в любом случае)... есть ли какая-либо реальная выгода, которую можно получить/рассмотреть/представить из-за того, что здесь не используется таблица delete?
myClass** table = new myClass* [size];
... //some code that does not reallocate or change the value of the table pointer ;)
delete table; // no [] intentionally
Ответы
Ответ 1
На самом деле нет причин писать так и серьезную причину, чтобы никогда этого не делать.
Верно, что для типов с тривиальными деструкторами (например, для raw-указателей в вашем случае) нет необходимости знать фактическое количество элементов в массиве, и поэтому компилятор может решить сопоставить новые [] и удалить [] на новые и delete, чтобы уменьшить накладные расходы. Если он решит таким образом, вы не сможете остановить его без дополнительных шагов, поэтому оптимизация компилятора будет проходить без вашего уведомления и будет бесплатной.
В то же время кто-то, использующий ваш код, может захотеть перегрузить глобальные операторы new и delete (и новые [] и удалить []). Если это произойдет, вы столкнетесь с большими неприятностями, потому что это может произойти, когда вам действительно понадобится различие между удалением и удалением [].
Добавьте к этому, что эта оптимизация, зависящая от компилятора, не переносима.
Итак, это так, когда вы не получаете никаких преимуществ, вытесняя delete [] с удалением, но рискуете большим временем, полагаясь на поведение undefined.
Ответ 2
Если вы это сделаете, вы получите то, что С++ Standard вызывает поведение undefined - все может произойти.
Ответ 3
Это утечка памяти. A new []
следует сопоставить с помощью delete []
. Кроме того, поскольку table
является указателем на первый элемент массива указателей, любой член массива, если он сам по себе должен быть выделен с помощью delete []
.
Ответ 4
Не только нет никакой пользы, код просто ошибочен - в лучшем случае он утечки памяти, и в худшем случае он может привести к сбою вашей программы или открыть труднодоступную дыру в безопасности. Вы всегда должны соответствовать new
с delete
и new[]
с помощью delete[]
. Всегда.
Ответ 5
Это определенно неверно, так как s new [] должен быть сопряжен с delete []. Если вы этого не сделаете, вы получите поведение undefined.
Он может работать (частично), потому что большинство реализаций используют новые для реализации новых []. Единственная разница для такой реализации заключалась бы в том, что она вызывала бы только один деструктор (для первого элемента вместо всех деструкторов, но избегайте его, поскольку он не легальный С++.
Ответ 6
В теории вы должны вызвать delete [].
EDIT: Следующее относится только к Microsoft Visual С++ (я должен был сказать это).
На практике в Microsoft Visual С++ не имеет значения, какое удаление вы используете, если объекты в массиве не имеют деструкторов. Поскольку у вас есть массив указателей, а указатели не могут иметь деструкторы, вы должны быть в порядке.
Однако, как указывали другие, неверно С++ смешивать новые [] и удалять без []. Хотя в этом случае он может работать на Visual С++, код не переносится и может быть неудачным в других компиляторах.
Но вернемся к конкретному случаю Visual С++, даже если вы вызываете delete [], компилятор поймет, что ему не нужно перебирать массив, вызывающий деструкторы, когда он представляет собой массив примитивных типов, таких как int, char или указатели. Вызов delete в этом случае фактически работает и ничего не сломает. Было бы медленнее делать правильные вещи и вызывать delete [], но это также не будет быстрее.
Фактически, в MSVС++ delete [] p сразу вызывает обычный оператор delete (void * p), когда p является указателем на простой тип или без деструкторов.
Те, кто мне не верит, выполните этот код в код CRT для первых двух вызовов для удаления [].
#include "stdafx.h"
#include <malloc.h>
#include <iostream>
using namespace std;
class NoDestructor
{
int m_i;
};
class WithDestructor
{
public:
~WithDestructor()
{
cout << "deleted one WithDestructor at " << (void *) this<< endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int **p = new int *[20];
delete [] p;
p = (int**) malloc(80);
free(p);
NoDestructor *pa = new NoDestructor[20];
delete [] pa;
WithDestructor *pb = new WithDestructor[20];
delete [] pb;
return 0;
}
Ответ 7
этот оператор оставит все объекты myClass, на которые указывают все указатели в массиве, висящем в памяти. Он также оставляет массив указателей в памяти. Нет никакого способа, который может быть полезен, поскольку он освобождает только 32 бит памяти, а ОС по-прежнему считает, что у вас есть (размер) myClasses и указатели для каждого используемого. Это просто пример программиста, который не очищается после себя должным образом.
Ответ 8
Обратитесь к разделу [16.11] "Как мне выделить/нераспределить массив вещей?" и далее в С++ FAQ Lite,
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.11
Они объясняют, что удаление массива является обязательным при создании массива.
Инстанс myClass, на который указывают элементы вашего массива, также должен быть удален там, где они созданы.