是否可以使用“delete this”来删除当前对象?

时间:2022-01-28 07:17:05

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?

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

8 个解决方案

#1


17  

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.

相反,您应该将temp->next()转换为temp变量。否则,您正在访问被删除的内存。

So more like this:

所以更多的是这样的:

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

#2


4  

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.

在DoublyLinkedList desturctor中也有一些问题。首先,删除temp,然后在它被删除后访问它。第二,代码实际上不会删除链表中的最后一个元素。

#3


4  

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();
}

#4


1  

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.

删除;将调用当前对象的析构函数。在这种情况下,如果你要调用delete;在析构函数中,析构函数会被无限调用直到崩溃。

#5


1  

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:

最重要的是:我真的,真的希望这是给你布置的家庭作业,为了理解一个双链表。否则就没有理由用这个代替std::list了。有了这些,

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

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

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.)

顺便说一句,它可能会工作,这当然是错误的,因为,当您尝试访问temp->next()时,temp已经被删除,所以您应该在它上调用一个成员函数。这样做会引发所谓的“未定义行为”。(简而言之:它可能做你想做的事,但也可能总是失败,或者偶尔失败,或者只有在13号星期五与新月碰撞的时候。)它也可能会让你的鼻子变得非常恶心。

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

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

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

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

这样,您的列表dtor也变得非常简单:

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.

对我来说,这似乎就是dtors发明的目的,所以,除了现在没有人应该再写他们自己的链表类型之外,对我来说,这似乎是你的问题的c++解决方案。

#6


0  

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

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

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

节点::~Node()不应该叫“删除这个”(否则你的程序会崩溃)

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.

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

#7


0  

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.

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

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.

顺便说一句,子类化也会发生同样的事情——如果你有类A,类B: public A,那么当你做一个新的B()时,A构造函数首先执行,然后是B的构造函数;在销毁时,B的析构函数首先执行,然后是A的。我敢肯定,您不必为此担心——c++会为您解决这个问题。因此,不要试图找到一种方法来调用超类中的delete。

#8


0  

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.

调用delete将导致所谓的double free,这也将导致未定义的行为。析构函数应该只对指针成员变量调用delete,而不是这个。从其他方法调用delete可以合理地释放当前对象,但不能从析构函数中释放。

#1


17  

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.

相反,您应该将temp->next()转换为temp变量。否则,您正在访问被删除的内存。

So more like this:

所以更多的是这样的:

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

#2


4  

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.

在DoublyLinkedList desturctor中也有一些问题。首先,删除temp,然后在它被删除后访问它。第二,代码实际上不会删除链表中的最后一个元素。

#3


4  

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();
}

#4


1  

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.

删除;将调用当前对象的析构函数。在这种情况下,如果你要调用delete;在析构函数中,析构函数会被无限调用直到崩溃。

#5


1  

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:

最重要的是:我真的,真的希望这是给你布置的家庭作业,为了理解一个双链表。否则就没有理由用这个代替std::list了。有了这些,

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

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

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.)

顺便说一句,它可能会工作,这当然是错误的,因为,当您尝试访问temp->next()时,temp已经被删除,所以您应该在它上调用一个成员函数。这样做会引发所谓的“未定义行为”。(简而言之:它可能做你想做的事,但也可能总是失败,或者偶尔失败,或者只有在13号星期五与新月碰撞的时候。)它也可能会让你的鼻子变得非常恶心。

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

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

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

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

这样,您的列表dtor也变得非常简单:

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.

对我来说,这似乎就是dtors发明的目的,所以,除了现在没有人应该再写他们自己的链表类型之外,对我来说,这似乎是你的问题的c++解决方案。

#6


0  

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

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

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

节点::~Node()不应该叫“删除这个”(否则你的程序会崩溃)

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.

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

#7


0  

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.

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

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.

顺便说一句,子类化也会发生同样的事情——如果你有类A,类B: public A,那么当你做一个新的B()时,A构造函数首先执行,然后是B的构造函数;在销毁时,B的析构函数首先执行,然后是A的。我敢肯定,您不必为此担心——c++会为您解决这个问题。因此,不要试图找到一种方法来调用超类中的delete。

#8


0  

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.

调用delete将导致所谓的double free,这也将导致未定义的行为。析构函数应该只对指针成员变量调用delete,而不是这个。从其他方法调用delete可以合理地释放当前对象,但不能从析构函数中释放。