应该在类

时间:2016-09-02 19:51:20

标签: c++ vector destructor

所以我已经有一段时间了,因为我已经完成了任何c ++编码,我只是想知道在析构函数中应该删除基本链表中的哪些变量,不幸的是我无法咨询我的关于此事的c ++手册。链表类如下所示:

#include <string>
#include <vector>

class Node
{
    Node *next;
    string sName;
    vector<char> cvStuff;

    Node(string _s, int _i)
    {
        next = nullptr;
        sName = _s;

        for (int i = 0; i < _i; i++)
        {
            cvStuff.insert(cvStuff.end(), '_');
        }
    }

    ~Node()
    {
         //since sName is assigned during runtime do I delete?
         //same for cvStuff?
    }
};

我也很好奇,如果在析构函数中我打电话

delete next;

是否会转到链接列表的下一个节点并删除该节点,从而以此方式从该点递归删除整个列表?另外,如果是这种情况并且由于某种原因我选择实现它,我是否必须在删除之前检查next是否为nullptr还是不会产生影响?

谢谢。

4 个答案:

答案 0 :(得分:1)

理想情况下,没有:使用智能指针:std::unique_ptr<>std::smart_ptr<>boost::scoped_ptr<>等。

否则,您删除拥有本机指针的内容。 next拥有吗?

  • 您打算删除列表中间的内容吗?如果是,则无法在析构函数中删除。
  • 你打算分享尾巴吗?如果是,您需要引用计数的智能指针。

可以删除nullptr(什么都不做)。在这个例子中,你不应该删除sName和cvStuff,因为它们是作用域的,因此会自动销毁。

此外,如果这将是一个可能变大的列表,您可能想要销毁&amp;手动释放*next。这是因为您不希望通过递归耗尽堆栈空间。

此外,我建议将此分隔为List,表示数据结构,ListNode表示元素。您的问题实际上表明了这种含糊不清,您不知道自己是否正在删除析构函数中的ListNodeList。将它们分开解决了这个问题。

答案 1 :(得分:1)

具有自动生命周期的对象在超出范围时调用它的析构函数:

{  // scope
    std::string s;
}  // end scope -> s.~string()

动态对象(使用new分配)没有调用它的析构函数,除非在其上调用delete

对于成员变量,范围是对象的生命周期。

struct S {
    std::string str_;
    char* p_;
};

int main() {  // scope
    {  // scope
        S s;
    }  // end scope -> s.~S() -> str_.~string()
}

在上面注意p_没有什么特别的事情发生:它是一个简单的标量类型的指针,所以代码不会自动执行任何操作。

因此,在您的列表类中,您唯一需要担心的是您的next成员:您需要确定它是否属于&#34;拥有&#34;指针与否。如果是拥有&#34;拥有&#34;然后你必须在析构函数中的对象上调用delete

或者,您可以利用&#39; RAII&#39; (资源获取是初始化)并使用对象来包装指针并提供将为您调用delete的析构函数:

{  // scope
    std::unique_ptr<Node> ptr = std::make_unique<Node>(args);
}  // end scope -> ptr.~unique_ptr() -> delete -> ~Node()

unique_ptr是一个纯粹拥有的指针,另一个替代方案可能是shared_ptr,它使用引用计数,以便当你没有时,底层对象只有delete d对象的任何剩余shared_ptr

如果您将next的实际地址保留在其他位置,您会认为您的Node指针是非拥有指针:

std::vector<Node> nodes;
populate(nodes);

list.insert(&nodes[0]);
list.insert(&nodes[1]);
// ...

在上面的例子中,向量拥有节点,你绝对不应该在delete析构函数中调用Node,因为Node不是你要删除的。

list.insert(new Node(0));
list.insert(new Node(1));

这里,列表/节点是唯一具有指向节点的指针,因此在这个用例中我们需要Node::~Node来调用delete或者我们有泄漏。

答案 2 :(得分:0)

基本上你应该

delete next 

那就是你应该做的一切:

只需将其全部删除即可。

答案 3 :(得分:0)

将调用您的类析构函数(它为空),然后调用成员对象析构函数。

如果member不是对象,则不会调用析构函数。

在你的例子中:

- List *next: pointer on List: no destructor called
- string sName: string object: destructor called
- vector<char> cvStuff: vector object: destructor called

好消息:你无事可做。析构函数声明在这里甚至没用。

如果在析构函数中删除next,则删除项目将删除列表中的所有其他项目:不是很有用。

(而你的List对象应该被称为Node)。 List是所有节点的链接结果,由您创建的第一个节点保存。