删除通过取消引用新对象初始化的对象
Posted
技术标签:
【中文标题】删除通过取消引用新对象初始化的对象【英文标题】:deleting object that was initialized by dereferencing new object 【发布时间】:2019-10-16 10:20:19 【问题描述】:我有以下课程:
现在我一直在考虑以这种方式实现我的构造函数:
基本上取消引用新操作返回的对象。 现在......这感觉不对,我可能应该使用指针,但我想挑战自己,也许让它发挥作用并学习新的东西。
所以我的问题将是删除这个对象......我的 Dense 析构函数不起作用,因为我有这样的:
但显然我遇到了这个错误:
free(): 无效指针
那么我怎样才能用我实现的方式释放分配的内存呢?
谢谢。
【问题讨论】:
你不能。在使用new
创建的对象来初始化另一个对象之后,构造函数中的初始化程序已经不遗余力地忘记了它们。析构函数具有未定义的行为,因为 &weights
等未分配给运算符 new
。
【参考方案1】:
没必要这么复杂。您可以直接从初始化列表中调用构造函数。这里绝对不需要new
。你也不需要delete
那些对象。如果Dense
被销毁,它们的析构函数将被自动调用。
Dense::Dense(): weights(), //Calls constructor Matrix()
bias(), //Calls constructor Matrix()
act(ActivationType::Relu), //Calls constructor Activation(ActivationType::Relu)
input() //Calls constructor Matrix()
此外,你试图用指针做什么也行不通。比如
&bias
就是成员变量bias的地址,与new Matrix()
返回的指针无关。
【讨论】:
是的,这很好地总结了我的问题,如果我要执行这种愚蠢的代码方式,我该如何删除 new Matrix() 返回的指针?有没有办法只用我有偏见的副本来做到这一点? 不,您必须存储由new Matrix()
返回的实际Matrix*
。【参考方案2】:
那么我怎样才能用我实现的方式释放分配的内存呢?
你根本做不到,你已经造成了内存泄漏。
说明:
当你写作时:
int a = *(new int(5)); // Really bad
你基本上是:
在堆上分配一个int
取消引用右值
将其分配(复制)到堆栈上的变量
您从不关心保留new
语句的返回指针。 a
是另一个 int
,它是您在堆上分配的副本。
您不能删除a
,因为它是在堆栈上创建的。由于a
是另一个对象,所以a
的地址与您在new
在堆上分配的int
的地址不同。
所以删除&a
显然是禁止未定义的行为,并且不能以任何方式删除您使用new
创建的int
。而且由于您没有存储 new
语句的返回指针,因此您无法检索它:这是内存泄漏。
如果您获得的是参考而不是副本,则可以将其删除:
int & a = *(new int(5));
delete &a; // fine
但这是一种过于复杂、效率较低且毫无意义的简单做法:
int a = 5; // destroyed at scope's end
【讨论】:
“显然禁止删除&a
”。努普。行为未定义,但没有规则禁止任何人这样做。 (这是否是一件好事,完全是另一个问题)。
@Peter 你是对的。对我来说,未定义的行为是被禁止的,但这只是个人规则。我会纠正它:)以上是关于删除通过取消引用新对象初始化的对象的主要内容,如果未能解决你的问题,请参考以下文章