Вопрос

У меня есть структура, подобная этой:

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[], вам нужно <=> его.
  • В опубликованном коде не указано, как распределяются объекты, на которые указывают массивы. Если вы размещаете эти объекты в стеке, вы не должны удалять их (опять же, это крайне маловероятно, поскольку ваши указатели станут недействительными, когда объекты, на которые они указывают, выпадают из области видимости). Если вы разместили их в куче (с новым), то вы должны удалить их, когда они выпадают из области видимости.
  • Как уже говорили другие, жизнь намного проще, если вы используете контейнер - особенно контейнер STL - и умные указатели - что на данный момент означает указатели из Boost.
  • C ++ - не моя сильная сторона, но я уверен, что вы потеряете память, если установите указатель на NULL.

    РЕДАКТИРОВАТЬ: Утечка памяти будет указывать указатель в массиве.

    Установка элементов [5] в NULL не удаляет память, связанную с элементом, она просто устанавливает указатель на этот элемент в NULL, поэтому память просачивается.

    Вы можете удалить элемент, позвонив по телефону:

    delete items[5];
    

    Поскольку в C ++ нет автоматической сборки мусора, вам нужно удалить любую память, которая вам больше не нужна.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top