为什么在删除类实例之后仍然可以访问它们?

14 浏览
0 Comments

为什么在删除类实例之后仍然可以访问它们?

我正在构建一个链表类,具有堆栈功能(LIFO),用于保存Node类的实例:

enum Sides{NorthWest=0, North=1, NorthEast=2, West=3, East=4, SouthWest=5, South=6, SouthEast=7};
class Node
{
    public:
    Node(position2df pos, int id):nextNode(NULL)
    {
        position=pos;
        ID=id;
    }
    ~Node(){}
    position2df getPosition(){return position;}
    int getID(){return ID;}
    void setPeripheralID(Sides side, int id){peripheralID[side]=id;}
    int getPeripheralID(Sides side){return peripheralID[side];}
    Node *nextNode;
    private:
    position2df position;
    int ID;
    int peripheralID[8];
};
class NodeList
{
    public:
    NodeList()
    {
        root=NULL;
        end=NULL;
    }
    ~NodeList(){}
    /// 向列表中添加元素的函数。
    void push(position2df pos, int id)
    {
        if(root==NULL)
        {
            root=new Node(pos, id);
            end=root;
        }
        else
        {
            Node *newend=new Node(pos, id);
            end->nextNode=newend;
            end=end->nextNode;
        }
    }
    /// 从列表中删除对象的函数。
    Node *pop()
    {
        slider=root;
        Node *previous;
        Node *next=slider;
        for(previous=NULL; next!=NULL; next=slider->nextNode)
        {
            previous=slider;
            slider=next;
        }
        delete slider;
        end=previous;
        cout << "删除对象后仍然可以访问:" << (*slider).getID() << endl;
        return end;
    }
    private:
    Node *root;
    Node *end;
    Node *slider;
};

NodeList::Node *pop()函数中(其目的是删除最后一个元素并将上一个元素重置为列表的末尾),我在指针名为slider的指向的Node类实例上调用delete。然而,即使在删除后,我仍然可以访问该实例并输出其成员。我不知道是否重要,但在删除时,该实例有三个不同的指针指向它。它们是:

  • Node *slider;
  • Node *end;
  • 上一个类实例的Node::Node *nextNode;

我想此时应该提问:D

如果在删除后仍然可以访问实例成员,我如何知道它是否已正确删除?

我的代码会导致内存泄漏吗?

我猜最重要的问题是:我做错了什么吗?

P.S. 这里有几个变量(position2df; vector2df;),它们来自Irrlicht游戏引擎。只是想指出这一点,以避免任何混淆。

如果我的问题表述含糊或不清楚,请原谅,我在在线提问方面并不很熟练。

0
0 Comments

为什么在删除实例后仍然可以访问类实例?

在调用delete之后,可以仍然访问实例成员,这是因为delete只是告诉系统你不再需要这块内存,系统会将这块内存重新分配给其他部分使用。虽然你仍然可以访问该内存,并且可能会找到删除之前的内容,但这是未定义行为。

那么,我代码会导致内存泄漏吗?

不会,因为你释放了你分配的内存。

那么,我是否做错了什么?

是的,访问已经释放的对象的内存是错误的(未定义行为)。除此之外,代码看起来是正确的。

所以,我需要手动将指向已删除内存块的指针设置为NULL吗?

将已删除的指针设置为NULL是一种常见的做法,但你不必这样做,不过这样做也不会有任何问题。

0
0 Comments

为什么在删除对象之后仍然可以访问类实例?

当删除一个对象时,它并不会立即被覆盖。对象所占用的内存区域仅仅被标记为"可用"。在内存被重新分配并初始化为其他用途之前,该内存区域不会被覆盖。

由于无法控制内存何时以及为何目的被重新分配,因此在删除对象后永远不应该再次访问该内存。为了确保这一点,在删除对象之前,所有指向被删除对象的指针都应该被设置为null。

但是通常情况下,在删除之后将所有指针设置为null是不可能的,因为该指针可能已经被复制了多次,而且你不知道这些指针的具体位置。我个人认为这样的建议是误导性的,对于典型情况并没有帮助,而且很可能会让人误认为指针的使用可以变得更安全。

解决这个问题的方法是在删除对象之前,尽量避免复制指针,并确保所有指向该对象的指针都被设置为null。此外,还可以使用智能指针等工具来管理内存,以避免出现访问已删除对象的情况。在编写代码时,应该始终注意内存的正确释放和管理,以避免引发这类问题。

0
0 Comments

问题原因:删除实例后仍然可以访问的情况并不是内存泄漏,而是未定义的行为,即即将发生崩溃的情况。

问题解决方法:要避免删除实例后仍然访问的问题,可以在删除实例后,将对应的引用或指针置为null或者空值。这样,当试图访问已删除的实例时,程序会抛出异常或者执行错误处理代码,从而避免发生崩溃。

以下是一个示例代码,演示了删除实例后访问的问题及解决方法:

public class MyClass {
    // Some class members and methods
    public static void main(String[] args) {
        MyClass instance = new MyClass();
        // Do something with the instance
        // Delete the instance
        instance = null;
        // Access the instance after deletion
        // This will lead to undefined behavior and may cause a crash
        // Some code here...
        // To avoid accessing deleted instances, set the reference to null
        MyClass anotherInstance = new MyClass();
        // Do something with anotherInstance
        // Delete anotherInstance
        anotherInstance = null;
        // Access anotherInstance after deletion
        if (anotherInstance != null) {
            // This will not execute since anotherInstance is null
            // Handle the error or throw an exception
        }
        // Some code here...
    }
}

在上述示例代码中,首先创建了一个名为instance的实例,并对其进行操作。然后将instance置为null,模拟删除实例的操作。接着,试图访问已删除的instance,这会导致未定义的行为和潜在的崩溃。

为了解决这个问题,我们在示例代码中创建了一个名为anotherInstance的新实例,并在删除anotherInstance后,使用if语句进行了判断,确保在访问已删除的实例时不会执行代码块。这样,即使尝试访问已删除的anotherInstance,程序也不会崩溃,而是执行错误处理代码或抛出异常。

删除实例后仍然访问可能导致未定义的行为和崩溃。为了避免这种情况发生,应在删除实例后将引用或指针置为null,以确保不会访问已删除的实例。

0