我们什么时候必须在派生类c++; 我对C++有点陌生,我正面临内存泄漏,这让我想我可能没有理解什么。

我们什么时候必须在派生类c++; 我对C++有点陌生,我正面临内存泄漏,这让我想我可能没有理解什么。,c++,destructor,virtual-destructor,C++,Destructor,Virtual Destructor,我有: .h文件 class DeliveryVehicle{ public: //c'tor DeliveryVehicle(const char* ID, Quality quality); //d'tor virtual ~DeliveryVehicle(); ... protected: VehicleParcelQueue parcelQueue_; } .c文件 DeliveryVehicle::~DeliveryVehicle(

我有:

.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*);
};
class VehicleParcelQueue:公共标准::队列{
公众:
常量static int MaxParcelsNum=5;
结果推送(包裹*);
};
.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;
}
typedef枚举结果{SUCCESS=1,FAILURE=0}结果;
结果车辆PARCELQUEUE::推送(地块*pParcel){
如果(size()>=5)返回失败;
否则{
队列::push(pParcel);
回归成功;
}
可以看出,在本例中,我没有显式实现析构函数。 我容易内存泄漏吗

也许pop并没有调用Parcle的delete,而是调用指向指针的析构函数?
谢谢车辆ParcelQueue中的默认析构函数不会删除
队列中指针指向的对象。这些对象是导致内存泄漏的原因

您必须为
车辆ParcelQueue
实现析构函数,并确保删除
队列中的所有
地块
对象。

前面的建议不起作用,因为将首先调用
队列
的析构函数

你最好的选择是使用

VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
VehicleParcelQueue:公共标准::队列{

VehicleParcelQueue:公共标准::队列{

车辆ParcelQueue
中的默认析构函数不会删除队列中指针指向的对象。这些对象是导致内存泄漏的原因

您必须为
车辆ParcelQueue
实现析构函数,并确保删除
队列中的所有
地块
对象。

前面的建议不起作用,因为将首先调用
队列
的析构函数

你最好的选择是使用

VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
VehicleParcelQueue:公共标准::队列{

VehicleParcelQueue:公共标准::队列{

当VehicleParcelQueue的实例超出范围时,将调用其析构函数,然后调用基类std::queue的析构函数。std::queue的析构函数将“释放”队列的节点,但不会为每个节点中存储的指针调用delete。您必须在VehicleParcelQueue的析构函数中手动执行此操作以避免泄漏。当然,如果其他对象仍引用这些对象,您也可能不希望删除这些对象

也许pop并没有调用Parcle的delete,而是调用指向指针的析构函数


正确。它会从队列中删除节点,但不会对指针调用delete。您必须获取节点的内容,即指针并对其调用delete。

当VehicleParcelQueue的实例超出范围时,将调用其析构函数,然后调用基类std::queue的析构函数。std的析构函数::队列将“释放”队列中的节点,但不会为每个节点中存储的指针调用delete。您必须在VehicleParcelQueue的析构函数中手动执行此操作以避免泄漏。当然,如果其他对象仍引用这些对象,您也可能不希望删除这些对象

也许pop并没有调用Parcle的delete,而是调用指向指针的析构函数


正确。它会从队列中删除节点,但不会对指针调用delete。您必须获取节点的内容,即指针并对其调用delete。

除了R Sahu answer之外,请注意
std::queue
析构函数是虚拟的,从指针到基的任何删除都将调用未定义的行为(因此,通常不应从标准容器继承)

您可能应该检查您的设计,例如使用类成员而不是继承,如果可能的话,将值优先于指针:

VehicleParcelQueue
{
    ...

    std::queue<Parcel> queue;
};
VehicleParcelQueue
{
...
std::队列;
};

除了R Sahu answer之外,请注意,
std::queue
析构函数是虚拟的,从指向基的指针中删除任何内容都将调用未定义的行为(因此,通常不应从标准容器继承)

您可能应该检查您的设计,例如使用类成员而不是继承,如果可能的话,将值优先于指针:

VehicleParcelQueue
{
    ...

    std::queue<Parcel> queue;
};
VehicleParcelQueue
{
...
std::队列;
};

您提供的代码没有内存泄漏,但您也没有显示完整的示例。您有没有理由不能使用
队列
?没有指针的代码比有指针的代码更简单。在这里完成后,您可能希望对代码进行进一步检查。请尝试codereview.stackexchange.com我发现了一些潜在的问题问题。您提供的代码没有内存泄漏,但您也没有显示完整的示例。有什么原因不能使用
队列
?没有指针的代码比有指针的代码更简单。在这里完成后,您可能希望对代码进行进一步检查。请尝试codereview.stackexchange.com我发现了一些潜在的问题问题。此解决方案有问题,因为正如R Sahu所指出的,std::queue的析构函数不是虚拟的。最好不要从中继承。此解决方案有问题,因为正如R Sahu所指出的,std::queue的析构函数不是虚拟的。最好不要从中继承。