删除 c++ 中的对象
我有一个 LinkedList,其中的 Node 有一个字段:
void* _data;
现在,我想删除此数据,但我不知道该数据是原始数据还是动态分配的对象。
因此,如果 write:
~Node() {
delete _node;
}
并且数据是动态分配的对象,它会调用该对象的析构函数还是会出现内存泄漏?
那么我怎样才能做到这一点呢?
I have a LinkedList with a Node that have a field:
void* _data;
Now, I want to delete this data, but i cant know if the data will be a primitive or an object that was dynamically allocated.
so, if a write:
~Node() {
delete _node;
}
and the data is an object that was dynamically allocated, will it call the destructor of the object or will i have a memory leak?
So how can I make this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不要这样做!
在
void指针
上调用delete
是一种未定义行为。[参考下面]未定义的行为意味着任何事情都可能发生,程序有时可能会崩溃,有时可能会工作,但你无法始终预测它的行为,这是一种非常糟糕的编程方式。
正如您正确地得出的结论,
void*
运算符无法确定它需要调用哪个类析构函数,最终导致未定义的行为。那么我怎样才能完成这项工作呢?
正如我所见,您拥有一个
void*
指针的目的是为了拥有一个通用的链接列表实现。 C++已经提供了模板化的通用链接列表std::list 为此目的,您可以使用它,因为重新发明轮子没有意义,而且标准链接列表实现很可能比通用链接列表的任何自定义实现版本更好。如果您仍然想要拥有自己的链接列表版本。您应该实现一个通用模板链接列表类,就像 std::list 所做的那样。
查看模板编程。
参考:
根据C++03 标准第 5.3.5/3 节:
脚注73)
Don't do that!
Calling
delete
on avoid pointer
is an Undefined Behavior.[Reference Below]Undefined Behavior means that anything can happen, the program might crash sometimes or might work sometimes but you cannot predict its behavior at all times, which is a very bad way of programing.
As you rightly concluded with
void*
there is no way that thedelete
operator can figure out which class destructor it needs to call, Eventually, leading to a Undefined Behavior.So how can i make this work?
As I see Your intention of having an
void*
pointer is for having a generic Link list implementation. C++ already provides a templated generic link list std::list for this purpose, You can use it as there is no point in re-inventing the wheel and it is most likely that the standard link list implementation will be better than any custom implemented version of a generic link list.If you would still want to have your own version of the link list. You should implement a generic template link list class just what std::list does.
Have a look at Template Programming.
Reference:
As per C++03 Standard section 5.3.5/3:
Foot Note 73)
如果您需要此行为,请使用模板。正如所写的,您的代码无法知道要调用哪个析构函数。
If you need this behavior, use a template. You code, as written, has no way to know what destructor to call.
当
_node
的类型为void*
时,delete _node
始终不正确,因为与delete
一起使用的操作数的类型必须始终是指向所构造对象的动态类型的指针,或者指向作为该类型的基类的类型的指针,前提是基类类型具有虚拟析构函数。显然,void*
无法满足该要求的任何一部分。如果您使用的是的方法,它可以在构造(或重置)时存储适当的删除器,并自动调用节点被破坏。
void*
,则需要在调用delete
之前找到某种方法将其转换回原始类型。另一种方法是使用类似于 std::shared_ptrWhen
_node
has typevoid*
,delete _node
is always incorrect because the type of the operand used withdelete
must always be a pointer to the dynamic type of the object constructed, or to a type that is a base class of that type, providing that the base class type has a virtual destructor. Clearly,void*
cannot fulfil either part of that requirement.If you are using a
void*
you need to find someway of casting back to the original type before callingdelete
. An altenrative approach would be to use something like astd::shared_ptr<void>
which can be used in a way where an appropriate deleter is stored at construction (or reset) time and will automatically be called with the node is destroyed.删除 void 指针是危险的。编译器可能会警告或拒绝您的代码。 C++ 标准规定您不应该这样做。
实际上,如果编译器确实接受您的代码,它只会释放内存而不调用析构函数。
Deleting a void pointer is dangerous. Compilers may warn or reject your code. The C++ standard says you shouldn't be doing so.
In practice, if the compiler does accept your code, it only frees the memory without calling the destructor.