这里使用"delete"真的会删除对象吗?
Will using "delete" here actually delete the object?
我正在使用 C++ 实现一个 LinkedList,在处理动态分配的内存时,我似乎忘记了一些事情。
我有一个节点class:
class Node {
public:
Node(int d) {
data = d;
next = NULL;
}
Node(int d, Node* n) {
data = d;
next = n;
}
int data;
Node* next;
};
在我的 LinkedList class 中,我有以下方法:
void remove(int n) {
Node* current;
current = head;
Node* previous = NULL;
while ( current->data != n && current->next != NULL) {
previous = current;
current = current->next;
}
if (current->data == n) {
previous->next = current->next;
current->next = NULL;
delete current;
}
else {
std::cout << "Node not found" << std::endl;
}
}
我好像忘记了..当我做 delete current
时会删除 Node
吗?就像指针 current
指向的实际对象一样?还是只是删除指针?或者使用 delete
删除指向动态分配内存的指针会同时删除指针和对象吗?或者我是否需要为此定义一个 Node class 析构函数?
它只是删除了它指向的结构——在你的例子中是节点——你仍然可以使用那个指针——让它指向另一个节点——事实上,没有办法删除指针本身,因为它是在堆栈上分配的.当您离开该功能时,它会自动 "deleted"。
p.s: 无需将 current->next 设置为 null
只删除free指向的内存。这具有以下含义:
- 您不能访问此位置的内存(释放后使用)
- 您的 Node 对象所需的内存量是免费的,这意味着您的程序将使用更少的 RAM。
- 指针本身指向无效位置或 NULL,如果您遵循最佳实践并手动将其设置为 NULL。
- 您的对象所在内存位置的数据可以被在此位置上具有有效指针的任何其他任务覆盖。所以从技术上讲,只要没有其他人覆盖它,节点数据仍然保留在内存中。
假设您已经使用指针上的 new delete 分配了对象,执行以下操作:
- 调用对象的析构函数
- 请求内存空闲(当发生这种情况时实际上是实现 dependent)
在某些时候内存管理器将释放并将其标记为进程不可访问。
因此,您可以在调用 delete 后将指针设置为约定的值。最好的做法是将其设置为最新编译器的 nullptr。
delete p
导致 p
指向的对象不复存在。这意味着
1、如果对象有析构函数,则调用;和
2. p
成为无效指针,因此任何取消引用它的尝试都是未定义的行为。
通常,该对象占用的内存再次可供程序使用,尽管这实际上是一个实现细节。
短语 "delete the pointer" 通常是 "delete the object pointed-to by the pointer" 的马虎 shorthand。
确实删除了current
指向的实际结构。指针保持不变。无需定义析构函数。
delete
运算符将应用于指向对象的指针。该指针是调用new
分配的堆上内存地址。在内部只有 table 个由 new
分配的地址。所以释放这种内存的关键就是那个地址。在您的情况下,此类地址存储在类型为 指向名为 current
.
的节点 的变量中
您的代码中几乎没有问题。有问题的是,您无法判断存储在 current 中的节点是否实际上分配在堆上。可能会发生当前节点分配在堆栈上的情况。例如
void someFunction(LinkedList &list) {
Node myLocalNode(10);
list.add(&myLocalNode);
list.remove(10); //<-- disaster happens here
}
这同样适用于静态分配的全局变量。
你必须处理极端情况。想一想当被删除的对象是第一个被变量 head
指向的对象时会发生什么。通过删除它的内存,您最终会在 head
中得到悬空指针,指向未分配的内存或其他人使用的内存。
我的第三个反对意见是完全不写这样的结构。我希望这只是一些学校练习,因为在任何其他情况下,您应该(几乎必须)使用一些现有列表,例如 C++ STL 中的 std::list
。
每当你在指针变量上调用 delete
时,它指向的对象就会从内存中删除,但是分配给实际指针变量的 4 个字节(在你的例子中,current
变量),这4个字节只有在变量超出范围时才会被释放,即函数结束时
我正在使用 C++ 实现一个 LinkedList,在处理动态分配的内存时,我似乎忘记了一些事情。
我有一个节点class:
class Node {
public:
Node(int d) {
data = d;
next = NULL;
}
Node(int d, Node* n) {
data = d;
next = n;
}
int data;
Node* next;
};
在我的 LinkedList class 中,我有以下方法:
void remove(int n) {
Node* current;
current = head;
Node* previous = NULL;
while ( current->data != n && current->next != NULL) {
previous = current;
current = current->next;
}
if (current->data == n) {
previous->next = current->next;
current->next = NULL;
delete current;
}
else {
std::cout << "Node not found" << std::endl;
}
}
我好像忘记了..当我做 delete current
时会删除 Node
吗?就像指针 current
指向的实际对象一样?还是只是删除指针?或者使用 delete
删除指向动态分配内存的指针会同时删除指针和对象吗?或者我是否需要为此定义一个 Node class 析构函数?
它只是删除了它指向的结构——在你的例子中是节点——你仍然可以使用那个指针——让它指向另一个节点——事实上,没有办法删除指针本身,因为它是在堆栈上分配的.当您离开该功能时,它会自动 "deleted"。
p.s: 无需将 current->next 设置为 null
只删除free指向的内存。这具有以下含义:
- 您不能访问此位置的内存(释放后使用)
- 您的 Node 对象所需的内存量是免费的,这意味着您的程序将使用更少的 RAM。
- 指针本身指向无效位置或 NULL,如果您遵循最佳实践并手动将其设置为 NULL。
- 您的对象所在内存位置的数据可以被在此位置上具有有效指针的任何其他任务覆盖。所以从技术上讲,只要没有其他人覆盖它,节点数据仍然保留在内存中。
假设您已经使用指针上的 new delete 分配了对象,执行以下操作:
- 调用对象的析构函数
- 请求内存空闲(当发生这种情况时实际上是实现 dependent)
在某些时候内存管理器将释放并将其标记为进程不可访问。
因此,您可以在调用 delete 后将指针设置为约定的值。最好的做法是将其设置为最新编译器的 nullptr。
delete p
导致 p
指向的对象不复存在。这意味着
1、如果对象有析构函数,则调用;和
2. p
成为无效指针,因此任何取消引用它的尝试都是未定义的行为。
通常,该对象占用的内存再次可供程序使用,尽管这实际上是一个实现细节。
短语 "delete the pointer" 通常是 "delete the object pointed-to by the pointer" 的马虎 shorthand。
确实删除了current
指向的实际结构。指针保持不变。无需定义析构函数。
delete
运算符将应用于指向对象的指针。该指针是调用new
分配的堆上内存地址。在内部只有 table 个由 new
分配的地址。所以释放这种内存的关键就是那个地址。在您的情况下,此类地址存储在类型为 指向名为 current
.
您的代码中几乎没有问题。有问题的是,您无法判断存储在 current 中的节点是否实际上分配在堆上。可能会发生当前节点分配在堆栈上的情况。例如
void someFunction(LinkedList &list) {
Node myLocalNode(10);
list.add(&myLocalNode);
list.remove(10); //<-- disaster happens here
}
这同样适用于静态分配的全局变量。
你必须处理极端情况。想一想当被删除的对象是第一个被变量 head
指向的对象时会发生什么。通过删除它的内存,您最终会在 head
中得到悬空指针,指向未分配的内存或其他人使用的内存。
我的第三个反对意见是完全不写这样的结构。我希望这只是一些学校练习,因为在任何其他情况下,您应该(几乎必须)使用一些现有列表,例如 C++ STL 中的 std::list
。
每当你在指针变量上调用 delete
时,它指向的对象就会从内存中删除,但是分配给实际指针变量的 4 个字节(在你的例子中,current
变量),这4个字节只有在变量超出范围时才会被释放,即函数结束时