Массив структур и создавать / удалять
-
10-07-2019 - |
Вопрос
У меня есть структура, подобная этой:
class Items
{
private:
struct item
{
unsigned int a, b, c;
};
item* items[MAX_ITEMS];
}
Допустим, я хотел "удалить" элемент, вот так:
items[5] = NULL;
И позже я создал новый элемент на том же месте:
items[5] = new item;
Нужно ли мне все еще звонить delete[]
чтобы все это убрать?Или это не понадобится, поскольку границы массива items[]
известны ли они до компиляции?
Допустима ли установка этого указателя в NULL или я должен вызывать delete там?
Решение
Вам нужно позвонить delete
, прежде чем установить его в NULL. (Установка его в NULL не требуется, это просто помогает уменьшить количество ошибок, если вы случайно попытаетесь разыменовать указатель после его удаления.)
Помните, что каждый раз, когда вы используете new
, вам нужно будет использовать new []
позже для того же указателя. Никогда не используйте одно без другого.
Кроме того, delete []
и <=> ведут себя одинаково, но вы никогда не должны смешивать <=> с <=> или <=> с <=>. В вашем примере, поскольку вы создали объект с помощью <=> (а не <=>, который будет создавать массив объектов), вы должны удалить объект с помощью <=> (а не <=>).
Другие советы
Как указал Клюге, таким образом вы бы пропустили объект с индексом 5.Но это действительно звучит так, как будто вы не должны делать это вручную, а использовать класс контейнера внутри Item
.Если вам на самом деле не нужно хранить эти item
объекты в качестве указателей используют std::vector<item>
вместо этого массива MAX_ITEMS
указатели.Вы также всегда можете вставить или стереть векторные элементы посередине, если вам нужно.
В случае, если вам нужно сохранить объекты в виде указателей (обычно, если struct item
на самом деле полиморфен, в отличие от вашего примера), вы можете использовать boost::ptr_vector<item> От Повышение.PtrContainer вместо этого.
Пример:
class Items {
private:
struct item {
unsigned int a, b, c;
};
std::vector<item> items;
}
if (items.size() > 5) // (just to ensure there is an element at that position)
items.erase(items.begin() + 5); // no need to use operator delete at all
Чтобы удалить элемент, используйте:
удалить элементы [5];
после удаления элемента желательно установить для удаленного указателя значение NULL, чтобы не возникало ошибок, если впоследствии вы снова удалите его по ошибке.
items [5] = NULL
Допустим, я хотел "удалить" элемент, вот так:
элементы[5] = NULL;
Я мало знаю Visual Basic, но это пахнет идиомой программирования Visual Basic, поскольку "Set a = None" (или Null, я не уверен) удалит объект, на который указывает a (или, скорее, уменьшит его количество ссылок для COM-объектов).
Как заметил кто-то еще, вы должны использовать либо:
delete items[5];
items[5] = newContent;
или:
delete items[5];
items[5] = NULL;
После delete[5]
, единственно возможное использование указателя , хранящегося в items[5]
это доставляет вам неприятности.Что еще хуже, так это то, что это может сработать в начале и начать давать сбой только тогда, когда вы выделите что-то еще поверх пространства, ранее используемого *items[5]
.Таковы причины, которые делают программирование на C / C ++ "интересным", т.е.действительно раздражает (даже для тех, кто любит C, как я).
Пишу просто delete items[5];
сохраняет то, что может оказаться бесполезной записью, но это преждевременная оптимизация.
Просто чтобы прояснить: вы ссылаетесь на вызов " delete[]
" ;. Я думаю, что вы имеете в виду delete
.
Я упоминаю об этом, потому что в C ++ есть два отдельных оператора, operator delete
и operator delete[]
. Последний используется для удаления массивов объектов, выделенных с помощью operator new[]
, и не применяется в этом случае. У вас есть массив указателей на объекты, которые вы должны инициализировать повторными вызовами operator new
, а не одним вызовом <=>.
Все, что я на самом деле пытаюсь сказать, это то, что вы используете <=> запутанно и неоднозначно; измените его на <=>.
Здесь есть несколько связанных вопросов:
<Ол>struct
не установлен, поэтому вам не нужно delete[]
массив. Если вы создали массив с помощью new[]
, вам нужно <=> его. C ++ - не моя сильная сторона, но я уверен, что вы потеряете память, если установите указатель на NULL
.
РЕДАКТИРОВАТЬ: Утечка памяти будет указывать указатель в массиве.
Установка элементов [5] в NULL не удаляет память, связанную с элементом, она просто устанавливает указатель на этот элемент в NULL, поэтому память просачивается.
Вы можете удалить элемент, позвонив по телефону:
delete items[5];
Поскольку в C ++ нет автоматической сборки мусора, вам нужно удалить любую память, которая вам больше не нужна.