C++ Как удалить элемент объекта по умолчанию, который является указателем
У меня есть тип, который имеет в качестве члена указатель на другой объект. Когда объект (Demo) создан, он инициализирует другой объект (Property) в конструкторе. Я полагаю, что если у меня много таких объектов, я бы не хотел тратить пространство кучи, когда я изменял свойство на что-то другое, поэтому я освобождаю инициализированную память в setProperty
затем в деконструкции демо я снова его удаляю, так как к этому моменту он будет установлен на что-то другое. Однако это приводит к сбою кода. Почему происходит сбой, если я переназначаюсь? property
когда это сбрасывается?
class Property{ };
class Demo{
protected:
Property *property;
public:
Demo(){ property = new Property();};
void setProperty(Property *p){
delete property;
property = p;
};
~Demo(){
delete property;
};
};
int main(){
Property p = Property();
Demo * d = new Demo();
d->setProperty(&p);
delete d;
}
2 ответа
Вы передаете адрес объекта, не созданного new
а затем попытаться delete
Это. Это неопределенное поведение.
Наиболее вероятное объяснение ускоренного курса состоит в том, что стандартная библиотека также освобождает Property p
, Вы сначала освобождаете его, затем в конце программы снова освобождаете p
,
Возможное "исправление" - передать объект, который может быть удален, т. Е. Создан new
,
int main(){
Property *p = new Property();
Demo * d = new Demo();
d->setProperty(p); // Demo is responsible for freeing `p`.
delete d;
} // standard libraries do clean up objects from `main` here
Обращаем ваше внимание, что существуют лучшие и более чистые способы реализации того, что вы пытаетесь сделать. Этот ответ только объясняет крах.
Вы должны увидеть это, это довольно сложно с этим решением выбрать, следует ли вам освободить или нет. Таким образом, ваш код зависит от происхождения параметра. Это должно быть красным флагом для дизайна.
Устраните все проблемы управления памятью, используя соответствующие инструменты, предоставляемые стандартной библиотекой.
#include <memory>
class Property{ };
class Demo{
protected:
std::unique_ptr<Property> property;
public:
Demo()
: property { new Property() }
{ }
void setProperty(std::unique_ptr<Property> p){
property = std::move(p);
};
// un-necessary
// ~Demo(){
// delete property;
// };
};
int main(){
auto p = std::unique_ptr<Property>(new Property); // or in c++14: = std::make_unique<Property>();
auto d = std::unique_ptr<Demo>(new Demo); // or in c++14: = std::make_unique<Demo>();
d->setProperty(std::move(p));
// no longer necessary
// delete d;
}