删除通过取消引用新对象初始化的对象

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 你是对的。对我来说,未定义的行为是被禁止的,但这只是个人规则。我会纠正它:)

以上是关于删除通过取消引用新对象初始化的对象的主要内容,如果未能解决你的问题,请参考以下文章

06—原型模式

试图取消引用一个接口,该接口是一个指向后端结构对象的指针,以便我可以按值传递给函数

拷贝构造函数

原型中的数组和对象 - 不被视为引用

java对象引用测试

引用另一个 UIViewController 导致一个 nil 指针并创建一个新对象