我是c ++的新手,我面临内存泄漏,这让我想知道我可能没有理解正确的事情。
我有:
.h文件
class DeliveryVehicle{
public:
//c'tor
DeliveryVehicle(const char* ID, Quality quality);
//d'tor
virtual ~DeliveryVehicle();
...
protected:
VehicleParcelQueue parcelQueue_;
}
.c文件
DeliveryVehicle::~DeliveryVehicle(){
while(!parcelQueue_.empty()) parcelQueue_.pop();
// pop() calls removed element destructor
}
我有一个派生类,我依赖于默认的析构函数,而不是显式实现析构函数。
我想知道,如果我不使用" new"来在派生类中分配内存,那是否可以。
另外,我实现了自己的固定大小队列,它继承了STL的基类队列:
.h文件
class VehicleParcelQueue:public std::queue<Parcel*>{
public:
const static int MaxParcelsNum = 5;
Result push(Parcel*);
};
.cpp文件
typedef enum result{SUCCESS = 1,FAILURE = 0} Result;
Result VehicleParcelQueue::push(Parcel* pParcel){
if (size() >= 5) return FAILURE;
else{
queue<Parcel*>::push(pParcel);
return SUCCESS;
}
可以看出,在这种情况下,我没有明确地实现析构函数。 我是否容易发生内存泄漏?
也许pop不会为Parcle调用delete而是将析构函数调用指针? 谢谢
答案 0 :(得分:4)
除了R Sahu的回答,请注意std::queue<>
析构函数不虚拟,从指针到Base的任何删除都会调用未定义的行为(因此,您通常不应该继承来自标准容器。)
您应该检查您的设计,例如使用类成员而不是继承,并在可能的情况下优先使用指针:
VehicleParcelQueue
{
...
std::queue<Parcel> queue;
};
答案 1 :(得分:1)
当VehicleParcelQueue的实例超出范围时,将调用其析构函数,然后调用基类std :: queue的析构函数。 std :: queue的析构函数将是&#34; free&#34;队列的节点,但不会为存储在每个节点中的指针调用delete。您必须在VehicleParcelQueue的析构函数中手动执行此操作以避免泄漏。当然,如果某些其他对象仍然引用它们,您可能也不想删除这些对象。
也许pop不会为Parcle调用delete而是将析构函数调用指针?
正确。它从队列中删除节点,但不会在指针上调用delete。您必须获取节点的内容,即指针和调用删除。
答案 2 :(得分:0)
VehicleParcelQueue
中的默认析构函数不会删除queue
中指针指向的对象。这些是导致内存泄漏的对象。
<击>
您必须为VehicleParcelQueue
实现析构函数,并确保删除Parcel
中的所有queue
个对象。
击>
之前的建议不会起作用,因为queue
的析构函数将首先被调用。
您最好的选择是使用
VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
或
VehicleParcelQueue:public std::queue<std::shared_ptr<Parcel>>{