我们什么时候必须在 derived class c++ 中定义析构函数
When do we have to define a destructor in derived class c++
我是 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
}
我有一个派生的 class,其中我依靠默认析构函数,而不是显式实现析构函数。
我想知道,如果我不使用 "new" 在派生 class 中分配内存,是否可以?
此外,我实现了自己的固定大小队列,它继承了 STL 的基础 Class 队列:
.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 而是为指针调用析构函数?
谢谢
VehicleParcelQueue
中的默认析构函数不会删除queue
中的指针指向的对象。这些是导致内存泄漏的对象。
您必须为 VehicleParcelQueue
实现析构函数,并确保删除 queue
中的所有 Parcel
对象。
之前的建议不会奏效,因为 queue
的析构函数将首先被调用。
你最好的选择是使用
VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
或
VehicleParcelQueue:public std::queue<std::shared_ptr<Parcel>>{
当 VehicleParcelQueue 的实例超出范围时,将调用其析构函数,随后调用基础 class std::queue 的析构函数。 std::queue的析构函数会"free"队列的节点,但不会对每个节点存储的指针调用delete。您必须在 VehicleParcelQueue 的析构函数中手动执行此操作以避免泄漏。当然,如果其他对象仍然引用它们,您可能也不想删除这些对象。
Maybe pop doesn't calling delete for Parcle but destructor to pointers?
正确。它从队列中删除节点,但不调用指针上的 delete。您必须获取节点的内容,即指针并对其调用 delete。
除了 R Sahu 的回答,请注意 std::queue<>
析构函数是 不是 虚拟的,任何从指向 Base 的指针的删除都会调用未定义的行为(出于这个原因,你通常不应该从标准容器继承)。
您可能应该检查您的设计,例如使用 class 成员而不是继承,并且尽可能使用值而不是指针:
VehicleParcelQueue
{
...
std::queue<Parcel> queue;
};
我是 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
}
我有一个派生的 class,其中我依靠默认析构函数,而不是显式实现析构函数。
我想知道,如果我不使用 "new" 在派生 class 中分配内存,是否可以?
此外,我实现了自己的固定大小队列,它继承了 STL 的基础 Class 队列:
.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 而是为指针调用析构函数? 谢谢
VehicleParcelQueue
中的默认析构函数不会删除queue
中的指针指向的对象。这些是导致内存泄漏的对象。
您必须为 VehicleParcelQueue
实现析构函数,并确保删除 queue
中的所有 Parcel
对象。
之前的建议不会奏效,因为 queue
的析构函数将首先被调用。
你最好的选择是使用
VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
或
VehicleParcelQueue:public std::queue<std::shared_ptr<Parcel>>{
当 VehicleParcelQueue 的实例超出范围时,将调用其析构函数,随后调用基础 class std::queue 的析构函数。 std::queue的析构函数会"free"队列的节点,但不会对每个节点存储的指针调用delete。您必须在 VehicleParcelQueue 的析构函数中手动执行此操作以避免泄漏。当然,如果其他对象仍然引用它们,您可能也不想删除这些对象。
Maybe pop doesn't calling delete for Parcle but destructor to pointers?
正确。它从队列中删除节点,但不调用指针上的 delete。您必须获取节点的内容,即指针并对其调用 delete。
除了 R Sahu 的回答,请注意 std::queue<>
析构函数是 不是 虚拟的,任何从指向 Base 的指针的删除都会调用未定义的行为(出于这个原因,你通常不应该从标准容器继承)。
您可能应该检查您的设计,例如使用 class 成员而不是继承,并且尽可能使用值而不是指针:
VehicleParcelQueue
{
...
std::queue<Parcel> queue;
};