删除以 void 指针作为成员的嵌套结构?
我有以下类:
class Stack {
struct Link {
void* data;
Link* next;
void initialize(void* dat, Link* nxt);
}* head;
public:
void initialize();
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
pop
方法是:
void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
oldHead
是指向 struct Link
的指针,该结构有一个 void 指针作为成员。因此,通过删除 oldHead
我就隐式删除了该 void 指针,对吗?
我正在阅读 Bruce Eckel 的《Thinking in C++》,它说删除 void 指针并不能正确清理问题,因为 delete
需要知道指针的类型。
此代码隐式删除 void 指针 data
,因此:有人可以解释一下为什么这种删除 void 指针的(隐式)方式与使用 delete
删除不同>?
I have the following class:
class Stack {
struct Link {
void* data;
Link* next;
void initialize(void* dat, Link* nxt);
}* head;
public:
void initialize();
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
The pop
method is:
void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
oldHead
is a pointer to a struct Link
, which has a void pointer as member. So by deleting oldHead
I'm implicitly deleting that void pointer, right?
I'm reading Thinking in C++ by Bruce Eckel, and it says that deleting void pointers doesn't clean things up properly because delete
needs to know the type of the pointer.
This code is implicitly deleting the void pointer data
, so: Can someone explain why is this (implicit) way of deleting a void pointer different from deleting with delete <void pointer>
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的术语引起了歧义,但让我解释一下。假设您有:
每当
foo
结束其生命周期时,bar
也会停止存在。因此,如果您有:您已经泄漏了,因为
new int
永远不会被删除。同样,当你这样做时:你仍然泄漏了,因为当运行
delete f
时,你只是结束了f
所指向的生命周期(就像自动发生的那样)上面),因此bar
不再存在,并且new int
不会被删除。总而言之,当对象的生命周期结束时,不会对指针成员调用
delete
。因此,当您在
Link
上调用 delete 时,与上面foo
中的bar
的情况相同:您正在删除Link
的内存>Link 导致data
停止存在,但实际上并没有删除它所指向的内容。Your terminology is causing ambiguity, but let me explain. Let's say you have:
Whenever a
foo
ends its lifetime,bar
simply stops existing too. So if you have:You've leaked, as
new int
is never deleted. Likewise, when you do:You've still leaked, since when
delete f
is run, you simply end the lifetime of whatf
is pointing to (just like what happened automatically above), ergobar
simply ceases to exist and thenew int
is not deleted.To summarize, when an object's lifetimes ends,
delete
is not called on the members that are a pointer.So when you call delete on a
Link
, it's the same situation asbar
infoo
above: you're deleteing the memory for aLink
causingdata
to stop existing, but not actually deleting what it's pointing at.通过删除
Link
,该 void* 内存空间不会被删除。您需要定义一个析构函数来删除已分配的内存。每个新的都需要一个删除。链接结构的一个示例是添加一个删除数据
的析构函数。如果您的假设是正确的,那么next
也会被删除,导致整个链接列表被删除,这将是一个可怕的行为。对指针调用delete将调用所指向类型的析构函数。如果该类型没有析构函数,则不会调用此类析构函数。这是没有析构函数的 void 指针的情况。在继承的情况下,析构函数应该始终是虚拟的,以便层次结构中最深的类将调用其析构函数。即使您将指针转换为错误的类型,内存也会被正确释放 - 只是析构函数将被错误地调用。
By deleting
Link
, that void* memory space is not being deleted. You need to define a destructor which deletes the memory that has been allocated. Each new needs one delete. An example of this for the Link-struct would be to add a destructor that deletesdata
. If your assumption would be correct, thennext
would also be deleted, causing your entire linked-list to be deleted which would be a terrible behavior.Calling delete on a pointer will call the destructor of the pointed to type. If that type has no destructor, no such destructor will be called. This is the case for a void pointer which doesn't have a destructor. In the case of inheritance, the destructor should always be virtual so that the deepest class in the hierarchy will have their destructor called. The memory will be correctly free'd even if you cast your pointers to the wrong types - it's just that the destructor will be called incorrectly.
“我正在隐式删除该 void 指针,对吗?”
好吧,当您删除
oldHead
时,您正在删除指针本身。您没有删除或释放其目标,这似乎是您想要的,并且是在指针上调用delete
时发生的情况。(要了解为什么会出现这种情况,请考虑您可能会定义一个带有指向该结构之外的内容的
void*
指针的结构。您不希望仅仅因为该结构就释放目标已被删除。)"I'm implicitly deleting that void pointer, right?"
Well, you're deleting the pointer itself when you delete
oldHead
. You're not deleting or freeing its target, which is what you seem to be wanting, and is what happens when you calldelete
on a pointer.(To see why this is the case, consider that you might define a struct with a
void*
pointer that points to something outside the struct. You wouldn't want the target to be freed just because the struct was deleted.)当您使用析构函数指向某个对象时,删除 void 指针会出现一个问题:
如果运行上面的代码示例,您将看到析构函数从未被调用。
One problem with deleting a void pointer happens when you are pointing to something with a destructor:
If you run the code sample above, you will see that the destructor is never called.