Можно ли удалить не новый объект?
У меня есть объект с вектором указателей на другие объекты в нем, что-то вроде этого:
class Object {
...
vector<Object*> objlist;
...
};
Теперь объекты будут добавлены в список двумя способами:
Object obj;
obj.objlist.push_back(new Object);
и
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
Если сделать деструктор, который просто
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Будут ли какие-либо неблагоприятные последствия с точки зрения того, когда он пытается удалить объект, который не был создан с помощью нового?
Ответы
Ответ 1
Да, будут неблагоприятные последствия.
Вы не должны delete
объект, который не был выделен new
. Если объект был выделен в стеке, ваш компилятор уже сгенерировал вызов его деструктору в конце своей области. Это означает, что вы дважды вызовите деструктор с потенциально очень плохими эффектами.
Кроме вызова деструктора дважды, вы также попытаетесь освободить блок памяти, который никогда не был выделен. Оператор new
предположительно помещает объекты в кучу; delete
ожидает найти объект в той же области, который оператор new
ставит. Однако ваш объект, который не был выделен new
, живет в стеке. Это, скорее всего, приведет к краху вашей программы (если она еще не сбой после вызова деструктора второй раз).
Вы также столкнетесь с серьезными проблемами, если ваш Object
в куче живет дольше, чем ваш Object
в стеке: вы получите свисающую ссылку где-нибудь в стеке, и вы получите неверные результаты /crash при следующем доступе к нему.
Общее правило, которое я вижу, это то, что материал, который живет в стеке, может ссылаться на материал, который живет в куче, но материал в куче не должен ссылаться на материал в стеке из-за очень высоких шансов, что они переберут объекты стека, И указатели на оба не должны смешиваться.
Ответ 2
Нет, вы можете только delete
, что вы new
ed
Object* anon = &name;
Когда имя выходит из области видимости, у вас будет неправильный указатель в вашем векторе.
Ответ 3
Это не сработает - если вы delete
объект, который не был выделен new
, вы нарушили правила или оператор delete
.
Если вам нужны объекты для хранения векторов, которые могут быть или не нуждаться в удалении, вам нужно как-то отслеживать их. Один из вариантов - использовать интеллектуальный указатель, который отслеживает, является ли объект, указывающий на объект, динамическим или нет. Например, shared_ptr<>
позволяет указать объект deallocator при построении shard_ptr<>
и, как указано в документах:
Например, дезактиватор "no-op" полезен при возврате shared_ptr к статически выделенному объекту
Тем не менее, вы должны быть осторожны при передаче указателей на автоматические переменные - если время жизни вектора больше, чем время жизни переменной, то в какой-то момент оно будет ссылаться на мусор.
Ответ 4
На самом деле вы спрашиваете, безопасно ли удалить объект, не выделенный через new
с помощью оператора delete
, и если да, то почему?
К сожалению, это запутывается некоторыми другими проблемами в вашем коде. Как уже упоминалось, когда имя выходит из области видимости, вы получите недопустимый указатель.
См. zneak answer, почему ваш исходный вопрос не приводит к безопасной операции и почему имеет значение область имени.