Можно ли удалить не новый объект?

У меня есть объект с вектором указателей на другие объекты в нем, что-то вроде этого:

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, почему ваш исходный вопрос не приводит к безопасной операции и почему имеет значение область имени.