【问题标题】:When do we have to define a destructor in derived class c++我们什么时候必须在派生类 c++ 中定义析构函数
【发布时间】:2015-03-18 01:35:36
【问题描述】:

我是 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 而是对指针调用析构函数? 谢谢

【问题讨论】:

  • 您提供的代码没有内存泄漏,但您也没有展示完整的示例。
  • 您是否有不能使用queue&lt;Parcel&gt; 的原因?没有指针的代码比有指针的代码简单。
  • 在此处完成后,您可能希望进一步审查您的代码。试试 codereview.stackexchange.com 我发现了几个潜在的问题。

标签: c++ destructor virtual-destructor


【解决方案1】:

除了 R Sahu 的回答,请注意 std::queue&lt;&gt; 析构函数 不是 虚拟的,任何从指向 Base 的指针中删除都会调用未定义的行为(因此,您通常不应该从标准继承容器)。

您可能应该检查您的设计,例如使用类成员而不是继承,并尽可能选择值而不是指针:

VehicleParcelQueue
{
    ...

    std::queue<Parcel> queue;
};

【讨论】:

    【解决方案2】:

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

    也许 pop 不是为 Parcle 调用 delete 而是对指针调用析构函数?

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

    【讨论】:

      【解决方案3】:

      VehicleParcelQueue 中的默认析构函数不会删除queue 中的指针指向的对象。这些是导致内存泄漏的对象。

      您必须为VehicleParcelQueue 实现析构函数并确保删除queue 中的所有Parcel 对象。

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

      你最好的选择是使用

      VehicleParcelQueue:public std::queue<std::unique_ptr<Parcel>>{
      

      VehicleParcelQueue:public std::queue<std::shared_ptr<Parcel>>{
      

      【讨论】:

      • 这个解决方案是有问题的,因为正如 R Sahu 所说,std::queue 的析构函数不是虚拟的。最好不要继承它。
      猜你喜欢
      • 1970-01-01
      • 2011-03-17
      • 2014-04-24
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      相关资源
      最近更新 更多