【问题标题】:Destructor inside a destructor?析构函数内的析构函数?
【发布时间】:2014-07-31 19:16:25
【问题描述】:

我正在尝试按对象删除分配的内存,但它是以链表的形式。有人可以建议一种方法吗?

这是我的头文件

class XKey
{   
public:
    XKey();
    virtual ~XKey();

private:
    char *m_name;
    char *m_value;
    XKey *m_next;
};

class XSection
{   
public:
    XSection();
    virtual ~XSection();  

private:    
    char *m_name;
    XKey *m_keys;
    XSection *m_next;
};

class XIniFile
{
public:
    XIniFile();
    virtual ~XIniFile();

private:
    char *m_name;
    XSection *m_sections;
};

这是我的程序文件

XKey::~XKey()
{
    delete(m_name);
    delete(m_value);
    m_next = 0;
}

XSection::~XSection()
{
    XKey k;
    XKey ks;

    k = m_keys;
    while (k){
        ks = k;
        k = k->getNext();
        //////////////<<<--- How can I call a destructor here from XKey?
        delete(m_name);
        m_keys = 0;
        m_next = 0;
    }
}

XIniFile::~XIniFile()
{
    XSection *sec;
    XSection *sp;

    sec = m_sections;
    while (sec) {
        sp = sec;
         //////////////<<<--- How can I call a destructor here from XSection?
        delete(m_name);
        m_sections = 0;
    }    

}

我有一些错别字,但请关注我如何在析构函数中调用析构函数的算法。谢谢!

【问题讨论】:

  • 您使用delete 调用析构函数,如delete kdelete s
  • “调用析构函数”是什么意思?您不会手动调用析构函数(除非您使用的是placement new,但那是另一回事)。当对象为delete'd 时会自动调用它们。此外,delete(sp-&gt;getName()); 很糟糕,表明您的数据结构缺乏封装和单一职责。
  • @BryanChen 不要使用指针。这里完全没有必要。
  • 恕我直言,以上所有 cmets 应形成一个社区答案 :)
  • @KonradRudolph 你的意思是不要使用 raw 指针?没有指针就无法实现链表。

标签: c++ destructor


【解决方案1】:

如果您将 RAII 与 std::stringstd::liststd::unique_ptr 一起使用, 您不必在析构函数中手动执行某些操作:

#include <list>
#include <string>
#include <memory> // unique_ptr

class XKey
{   
public:
    virtual ~XKey() = default;

private:
    std::string m_name;
    std::string m_value;
};

class XSection
{   
public:
    virtual ~XSection() = default;

private:
    std::string m_name;
    std::list<std::unique_ptr<XKey>> m_keys;
};

class XIniFile
{
public:
    virtual ~XIniFile() = default;

private:
    std::string m_name;
    std::list<std::unique_ptr<XSection>> m_sections;
};

如果这些类不需要是多态的,您可以使用std::list&lt;T&gt; 而不是std::list&lt;std::unique_ptr&lt;T&gt;&gt;

【讨论】:

  • 我还不太了解列表,所以我更喜欢下面的答案。不过还是谢谢..
【解决方案2】:
XSection::~XSection()
{
    XKey* k = m_keys;   // must be a pointer!

    while (k){
        XKey* ks = k;   // must be a pointer!
        k = k->getNext();
        if (ks != nullptr) delete ks;
    }
    delete [] m_name; // allocated with new[]?
}

这是非常c++98,你应该考虑拥抱c++11(智能指针)

【讨论】:

  • 事实上,没有。 XKey 的析构函数应该改为 delete this-&gt;next;。再次,封装和单一职责。此外:if (ks != nullptr) delete ks; - 在删除之前对对象进行空值检查是没有用的,delete nullptr; 是一个安全的空操作。
  • @TheParamagneticCroissant:你说得对,XKey 是一个链表,因此它应该自行删除。我不会编辑,因为应该使用 std::vector (或类似的)
  • 不,你不能这么肯定地说。这样的列表的经典实现(没有vector后端)是可以的。请注意,矢量不允许轻松移动项目。移动,插入,擦除..它们都会强制重新分配/移动许多其他条目。这与在XKey::~XKey 中执行的简单delete[]value; 配对会破坏/使您碰巧保留在局部变量中的许多XKeys 无效。这正是您想要的效果以防止您使用列表而不是数组。只有像 vector+sharedpointer 这样的东西才能做到这一点,但这反过来又会改变一切。
  • @quetzalcoatl 这就是为什么我们使用std::list 来代替我们需要类似列表的性能特征的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 2018-08-29
  • 2014-05-27
  • 2011-04-16
  • 2011-04-03
  • 2010-12-16
相关资源
最近更新 更多