使用“删除此”可以吗? 删除当前对象?

发布于 2024-08-01 15:58:55 字数 524 浏览 2 评论 0原文

我正在编写一个链表,我希望结构的析构函数(Node 结构)能够简单地删除自身,并且不会产生任何副作用。 我希望我的列表的析构函数迭代地调用自身的 Node 析构函数(临时存储下一个节点),如下所示:

//my list class has first and last pointers
//and my nodes each have a pointer to the previous and next
//node
DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();

    while (temp->next() != NULL)
    {
        delete temp;
        temp = temp->next();
    }
}

所以这将是我的 Node 析构函数:

Node::~Node
{
   delete this;
}

这可以接受吗,尤其是在这种情况下?

I'm writing a linked list and I want a struct's destructor (a Node struct) to simply delete itself, and not have any side effects. I want my list's destructor to iteratively call the Node destructor on itself (storing the next node temporarily), like this:

//my list class has first and last pointers
//and my nodes each have a pointer to the previous and next
//node
DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();

    while (temp->next() != NULL)
    {
        delete temp;
        temp = temp->next();
    }
}

So this would be my Node destructor:

Node::~Node
{
   delete this;
}

Is this acceptable, especially in this context?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

烟柳画桥 2024-08-08 15:58:55

如果 Node 析构函数被调用,那么它已经在被删除的过程中。 因此,删除在 Node 析构函数中没有意义。

这也是错误的:

while (temp->next() != NULL)
{
     delete temp;
     temp = temp->next();
}

相反,您应该将 temp->next() 放入临时变量中。 否则您将访问已删除的内存。

所以更多的是这样的:

DoublyLinkedList::~DoublyLinkedList
{
  Node *temp = first();
  while (temp != NULL)
  {
       Node *temp2 = temp->next();
       delete temp;
       temp = temp2;
  }
}

If the Node destructor is being called, then it's already in the process of being deleted. So a delete doesn't make sense inside your Node destructor.

Also this is wrong:

while (temp->next() != NULL)
{
     delete temp;
     temp = temp->next();
}

Instead you should get temp->next() into a temp variable. Otherwise you are accessing deleted memory.

So more like this:

DoublyLinkedList::~DoublyLinkedList
{
  Node *temp = first();
  while (temp != NULL)
  {
       Node *temp2 = temp->next();
       delete temp;
       temp = temp2;
  }
}
披肩女神 2024-08-08 15:58:55

不,你不应该从析构函数中删除它。 由于删除语句(或超出范围)而调用析构函数,这很可能会导致某种崩溃。

DoublyLinkedList 析构函数中还存在一些问题。 一,删除 temp,然后在删除 temp 后访问 temp。 其次,代码实际上不会删除链表中的最后一个元素。

No you should not delete this from the destructor. The destructor gets called because of a delete statement (or goes out of scope) and this would most likely lead to some sort of crash.

You also have a couple problems in the DoublyLinkedList desturctor. One, you delete temp then access temp after its been deleted. Second, the code will not actually delete the last element in the linked list.

淤浪 2024-08-08 15:58:55

目前,您的代码会导致访问冲突,因为以下行中的第二行清楚地访问了已释放的内存:

delete temp;
temp = temp->next();

如果您想递归删除该结构,您需要如下所示的内容:

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    delete temp;
}

Node::~Node
{
   if(this->next() != NULL) delete this->next();
}

Currently, your code would cause an access violation, since the second of the following lines clearly accesses freed memory:

delete temp;
temp = temp->next();

If you want to recursively delete the structure, you want something like this:

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    delete temp;
}

Node::~Node
{
   if(this->next() != NULL) delete this->next();
}
水水月牙 2024-08-08 15:58:55

首先:我真的非常希望这是布置给您的家庭作业,以便您理解双向链表。 否则没有理由使用它来代替 std::list。 解决这个问题:

不,在 dtor 中 delete this 总是错误的,因为当 this 处于被删除状态时会调用 dtor。

另外,虽然

delete temp;
temp = temp->next();

偶然可能有效,但它肯定是错误的,因为当您尝试访问 temp->next() 时,temp 已被删除,因此您应该调用成员函数就可以了。 这样做会引发所谓的“未定义行为”。 (简而言之:它可能会做你想做的事,但它也可能总是或偶尔失败,或者仅在 13 号星期五与新月相撞时失败。它还可能会在你身上引发非常令人讨厌的鼻恶魔.)

请注意,您可以通过删除节点 dtor 中的下一个节点来解决这两个问题:

Node::~Node()
{
   delete next();
}

这样,您的列表 dtor 也变得非常容易:

DoublyLinkedList::~DoublyLinkedList()
{
    delete first();
}

对我来说,这似乎是 dtor 的发明目的,所以,除了没有人这样做的事实现在应该不再编写自己的链表类型了,对我来说,这似乎是您问题的C++ 解决方案

Before anything else: I really, really hope this is homework assigned to you in order to understand a doubly linked list. Otherwise there is no reason to use this instead of std::list. With this out of the way:

No, delete this in a dtor is always wrong, as the dtor is called when this is in the state of being deleted.

Also, while

delete temp;
temp = temp->next();

incidentally might work, it's certainly wrong, since, where you attempt to access temp->next(), temp is already deleted, so you should call a member function on it. Doing so invokes so-called "undefined behavior". (In short: It might do what you want, but it might just as well fail always or sporadically or only when Friday, 13th, collides with new moon. It migh also invoke very nasty nasal demons on you.)

Note that you could solve both problems by deleting the next node in your node's dtor:

Node::~Node()
{
   delete next();
}

That way, your list dtor becomes very easy, too:

DoublyLinkedList::~DoublyLinkedList()
{
    delete first();
}

To me, this seems what dtors were invented for, so, except for the fact that nobody should write their own linked list types anymore nowadays, to me this seem to be the C++ solution to your problem.

み零 2024-08-08 15:58:55

删除这个; 会调用当前对象的析构函数。 在这种情况下,如果您打电话删除此; 在析构函数中,那么析构函数将被无限调用,直到崩溃。

delete this; would call the destructor of the current object. In that case, if you are calling delete this; in the destructor, then the destructor would be called infinitely till the crash.

彡翼 2024-08-08 15:58:55

一般来说,析构函数应该只关心删除(或者释放,如果您使用的是 C 或 malloc)专门为您的对象分配的任何内存。 删除指向对象的指针始终由操作系统管理,您不必担心该部分的任何事情。

值得记住的一件事是,在构造时,首先创建对象(当控制流进入构造函数的主体时),然后创建内部的对象; 对于销毁,您必须反向执行此操作,因为如果您先删除外部对象,您将无法访问内部指针来删除它们。 相反,您使用析构函数删除内部对象,然后当控制流脱离析构函数时操作系统管理实际的内存释放。

顺便说一句,子类化也会发生同样的事情——如果你有类 A 和类 B : public A,那么当你执行 new B() 时,首先执行 A 构造函数,然后执行 B 的构造函数; 销毁时,B 的析构函数首先执行,然后是 A 的析构函数。 不过,我相当确定您不必担心这一点——C++ 会为您解决这个问题。 因此,不要试图找出在超类上调用删除的方法。

In general, a destructor should just worry about delete-ing (or free-ing if you're using C or malloc) any memory allocated specifically for your object. Deleting a pointer to your object will always be managed by the OS and you don't have to worry about a thing about that part.

One thing worth keeping in mind is that, on construction, you create the object first (as control flow enters the constructor's body), THEN the objects inside; for destruction, you have to do that in reverse, because if you delete the outer object first you would have no way to access the inner pointers to delete those. Instead, you delete inner objects using the destructor, then the OS manages the actual freeing up of memory when control flow falls out of the destructor.

Incidentally, the same sort of thing happens with subclassing-- if you have class A, and class B : public A, then when you do a new B(), the A constructor executes first, then the B's constructor; on destruction, the B's destructor executes first, followed by A's. I'm fairly sure that you do NOT have to worry about this, though-- C++ takes care of it for you. So don't try to figure out a way to call delete on the superclass.

2024-08-08 15:58:55

上面的代码将调用 Node::~Node() 两次。 (在“delete temp”和 Node::~Node() 中)

::~Node() 不应该调用“delete this”(否则你的程序会崩溃)

Node 你的代码中的 while 循环将不起作用。 它将取消引用无效指针。
您应该首先复制 temp->next 的值,然后销毁 temp 指针。

Code above will call Node::~Node() twice. (in "delete temp" and in Node::~Node())

Node::~Node() should not call "delete this" (or your program will crash)

ps. while loop in your code will not work. It will dereference invalid pointer.
You should first copy the value of temp->next, and then destroy temp pointer.

猛虎独行 2024-08-08 15:58:55

两者都不应该做。

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    while (temp->next() != NULL)
    {
        delete temp;
        temp = temp->next();
    }
}

将导致未定义的行为 - 您不允许访问已返回到堆的内存。 相反,它应该是:

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    while( temp != NULL)
    {
        Node* next = temp->next();
        delete temp;
        temp = next;
    }
}

调用delete this将导致所谓的双重释放,这也会导致未定义的行为。 析构函数应该只对指针成员变量调用delete,而不能对this调用delete。 从其他方法调用 delete this 来释放当前对象是合理的,但在析构函数中则不然。

Both should never be done.

This

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    while (temp->next() != NULL)
    {
        delete temp;
        temp = temp->next();
    }
}

will cause undefined behaviour - you're not allowed to access memory that you've returned to the heap. Instead it shoud be:

DoublyLinkedList::~DoublyLinkedList
{
    Node *temp = first();
    while( temp != NULL)
    {
        Node* next = temp->next();
        delete temp;
        temp = next;
    }
}

Calling delete this will lead to so-called double free which will also cause undefined behaviour. The destructor should only call delete for pointer member variables, never for this. Calling delete this is reasonable from other methods to deallocate the current object, but not from the destructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文