Я пишу шаблонный класс, который берет в качестве входа указатель и хранит его. Указатель предназначен для указания на объект, выделенный другим классом и врученный этому содержащему класс.
Теперь я хочу создать деструктор для этого контейнера. Как я должен освободить память, на которую указывает этот указатель? У меня нет способа знать априорно, является ли это массивом или единственным элементом.
Я - вид новых для C++, поэтому терпите меня. Я всегда использовал C, и Java является моим предпочтительным языком OO, но между желанием изучить C++ и требования к скорости моего проекта, я пошел с C++.
Это была бы лучшая идея изменить контейнер от шаблона до контейнера для абстрактного класса, который может реализовать его собственный деструктор?
Если вы не знаете, был ли он выделен с помощью new
или new []
, то это небезопасно удалять его.
Ваш код может работать. Например, на одной платформе, над которой я работаю, разница имеет значение только тогда, когда у вас есть массив объектов с деструкторами. Итак, вы делаете это:
// by luck, this works on my preferred platform
// don't do this - just an example of why your code seems to work
int *ints = new int[20];
delete ints;
, а затем делаете это:
// crashes on my platform
std::string *strings = new std::string[10];
delete strings;
Краткий ответ:
Если вы используете [] с new, вы хотите использовать [] с delete.
//allocate some memory
myObject* m = new myObject[100];
//later on...destructor...
delete m; //wrong
delete[] m; //correct
Это были голые кости, еще одна вещь, на которую вы могли обратить внимание, - это boost . Также довольно сложно ответить, учитывая, что вы не уверены, массив это или один объект. Вы можете проверить это с помощью флага, сообщающего вашему приложению, следует ли использовать delete или delete [].
Поскольку указатель в C ++ не сообщает нам, как он был выделен, да, нет способа решить, какой метод освобождения использовать. Решение состоит в том, чтобы предоставить выбор пользователю, который, надеюсь, знает, как была выделена память. Взгляните на библиотеку Boost smart ptr , особенно на конструктор shared_ptr со вторым параметром, как отличный пример.
Причина использования альтернативной системы кодирования, отличной от HTML, заключается в безопасности
Уценка и другие такие системы кодирования в стиле вики обычно не поддерживают языки сценариев
HTML поддерживает языки сценариев многими способами (
Две основные проблемы безопасности:
Преступники вредоносного ПО используют скрипты в пользовательском контенте для попытки вредоносных действий на компьютере считывателей контента путем создания скриптов для доступа к известным защитным отверстиям
Бесплатные загрузчики, использующие скрипты для подрыва остальной части сайта путем изменения фрейма контента или стилей, т.е. рекламы, меню, логотипов и т.д. Это также может быть преступное поведение, если не просто раздражает
Используя промежуточный язык, такой как уценка, вы имеете полный контроль над визуализированным выводом
Фильтрация HTML возможна, но также является сложной и рискованной
Другой важной причиной альтернативной системы кодирования является применение стиля. Обычный HTML имеет слишком много параметров. Ограничивая доступные параметры, пользователи могут использовать только определенные стили. Обычно это делает более чистый и читаемый контент (сравните SO с Ebay)
-121--2875902- Если число предметов, возвращающих значение true
, совпадает с числом всех предметов, то возвращает значение true
. Просто как это:
Driveway.Cars(a => a.Red).Count() == Driveway.Cars.Count()
Родственное объяснение: Почему «abcd». StarstWith («») возвращает true?
-121-1118509-(Перемещение моего комментария в ответ, по запросу.)
Ответ JonH правильный (об использовании разрушения массива только при использовании построения массива), так что, возможно, вы один для массивов, другой нет.
Другой ответ состоит в том, чтобы избежать массивов и вместо этого ожидать одного экземпляра, который может быть или не быть правильным набором, который очищается после себя, например, вектор < >.
изменить
Вопиюще украсть у Роджера Пейта, добавлю, что может потребоваться использование смарт-указателя, что равносильно коллекции из одного элемента.
Вы не должны удалять его вообще. Если ваш класс принимает уже инициализированный указатель, удалять его небезопасно. Он может даже не указывать на объект в куче; вызов либо delete
, либо delete []
может иметь катастрофические последствия.
Выделение и освобождение памяти должно происходить в одной и той же области. Какой-либо код владеет и инициализирует экземпляр вашего класса, также предположительно отвечает за инициализацию и передачу указателя, и , что - это то место, где должно быть ваше delete
.
Проще говоря, имея только указатель на динамически выделяемую память, невозможно определить, как безопасно освободить ее. Указатель мог быть размещен любым из следующих способов:
Во всех случаях, прежде чем вы сможете освободить память, вы должны знать, как она была выделена.
Если у вас есть класс, который принимает указатель, владельцем которого он станет, тогда контракт на использование класса должен включать одну из пары вещей. Либо:
или
delete
указателя, например, может сделать его столь же простым в использовании, как вариант 1 для большинства применений). Теперь, если кто-то хочет дать классу указатель на статически выделенный объект, он может передать функтор без операции, чтобы ничего не произошло, когда класс хочет освободить его, или функтор на delete []
операция, если объект был выделен new []
и т. д. Умный указатель, такой как boost shared_pointer, уже покрыл это, могли бы вы его использовать? линки
Вы должны задокументировать, как этот класс ожидает использования, и всегда выделять, как ожидалось. Вы также можете передать объекту флаг, определяющий способ его уничтожения. Также обратите внимание на интеллектуальные указатели boost , которые помогут вам справиться с этим различием.
Как правило, вы должны придерживаться дизайна, в котором класс, вызывающий new
, также должен вызывать delete
delete
, если вы разместили с помощью new
. delete []
, если вы разместили new []
. После этих утверждений, если у вас все еще есть проблема (возможно, вы хотите удалить объект, созданный кем-то другим), вы нарушаете третье правило: