Mat*_*Mut 48 c++ destructor lifetime
免责声明:我知道这是一个糟糕的设计,我只是出于好奇而问这个问题,以便尝试深入了解析构函数在C++中是如何工作的.
在C#中,可以编写:GC.KeepAlive(this)在类的析构函数中(参见下面的编辑),这意味着即使在析构函数调用完成后,该对象仍将在内存中存活.
C++的设计是否允许从析构函数中恢复一个类似于上述C#算法的对象?
编辑:正如下面的答案所指出的,GC.ReRegisterForFinalize()与问题的关系更为密切GC.KeepAlive(this).
Sam*_*hik 100
最简洁的答案是不.C++不使用垃圾收集,如Java或C#.当一个物体被摧毁时,它会立即被摧毁.过得好.加入合唱团看不见.渴望峡湾等......
并且用不同的词语多次说出来,这样就不可能轻易地重新解释......
析构函数作为对象销毁的一部分被调用.对象破坏包括调用析构函数和释放用于对象本身的内存.这是一个单一的过程,而不是两个独立的过程.析构函数在运行时,对象仍然存在,供析构函数使用,但它存在于借来的时间.一旦析构函数返回,对象就会被蒸发,这已成定局.一旦调用析构函数,该对象将被销毁,并且没有任何东西会改变它的命运.
理解这一点:调用析构函数的原因是:对象最初是在堆上用"new"分配的,现在它正在"删除"d."删除"表示"删除",而不是"删除可能".所以对象被删除了.或者,如果对象是在堆栈上分配的,则执行线程退出范围,因此范围中声明的所有对象都将被销毁.从技术上讲,析构函数是由于对象被销毁而被调用的.所以,对象正在被摧毁.结束.
话虽如此,C++允许您为类实现自定义分配器.如果您愿意,可以编写自己的自定义内存分配和释放功能,以实现您想要的任何功能.虽然这些从未用于堆栈分配的对象(即局部变量).
Nin*_*rry 52
你实际上是GC.KeepAlive在歪曲.NET中的内容.它不能用在对象的析构函数中以防止该对象被破坏 - 实际上,它GC.KeepAlive()是空的并且没有实现.请在此处查看.NET源代码.
它确保在调用发生之前不会将作为参数传递的对象进行垃圾回收GC.KeepAlive.作为参数传递给KeepAlive的对象可以在调用后立即进行垃圾回收GC.KeepAlive.由于KeepAlive没有实际的实现,这纯粹基于编译器必须维护对作为参数传递的对象的引用这一事实KeepAlive.也可以使用将对象作为参数的任何其他函数(未由编译器或运行时内联).
这是一个想法:
C* gPhoenix= nullptr;
C::~C ()
{
gPhoenix= new C (*this); // note: loses any further-derived class ("slice")
}
Run Code Online (Sandbox Code Playgroud)
现在,如果所涉及的对象(基础或成员)确实具有可以执行某些操作的析构函数,那么如果您delete gPhoenix;需要更复杂的机制(这取决于它真正想要实现的内容),则会遇到问题.但你没有任何真正的目标,只是好奇的探索,所以指出这一点就足够了.
当析构函数的主体被调用时,该对象仍然非常好.当您从析构函数中进行正常的成员函数调用时,它看起来非常重要和正常.
拥有该对象的内存将被回收,因此您无法就地固定.离开身体后,其他破坏会自动发生,不会受到干扰.但是,您可以在此之前复制对象.
正如已经指出的那样,GC.KeepAlive不这样做.
只要.NET运行,就可以从终结器中恢复使用GC.ReRegisterForFinalize,如果你有一个WeakReference或GCHandle跟踪的ressurection,你仍然可以得到它的引用,或者只是给this类外的东西.这样做会中止破坏.
这是检测.NET 2.0中的垃圾收集不再相关的一个老技巧,但仍然有效(有点,垃圾收集现在可以是部分的,并且与其他线程并行完成).
应该强调的是,在.NET上你使用的是终结器,它在破坏之前运行,并且可以防止它.因此,虽然在技术上正确无法在销毁后恢复对象(使用任何语言),但您可以接近在.NET中描述的行为,除非使用GC.ReRegisterForFinalize.
在C++上,您已经得到了正确的答案.
| 归档时间: |
|
| 查看次数: |
4506 次 |
| 最近记录: |