在同一个类的析构函数和垃圾收集中的对象实例化

时间:2011-06-21 08:29:30

标签: c# c++ object garbage-collection instantiation

最近,在介绍一个专注于面向对象编程的入门单元时,我被引入了C#中的垃圾收集器,它的作用是“清理”不再被引用的对象。然后我介绍了析构函数,以及在删除对象之前如何调用它们。

当然,我开始思考,但我从没想起要问讲师这件事;如果在同一个类的析构函数中创建一个类的实例会发生什么?

C#示例

class Person{
 ~Person(){

  Person p = new Person();
  Console.WriteLine("Person destroyed");

 }
}

class Program{
 static void Main(string[] args){
  Person p = new Person();
 }
}

我想从更理论的角度来看待这个问题,所以我不情愿(在现阶段)尝试它,因为我可能不会理解,但我有一些理论。此外,我现在不在我的普通电脑上;)

  • Person .~Person()将会递归,因为每次创建新Person时,它都会调用它的析构函数并无限制地创建一个新的Person,或者直到发生某种与内存相关的异常。随后,主将永远不会终止。
  • 编译器会抱怨(无论如何,将此选项添加到每个场景似乎都是个好主意。)
  • 不知何故,会发生某种“析构函数跳过”。即。对象破坏不会按顺序调用,因此构造函数也不会被调用。

现在提出一个类似的相关问题。如果垃圾收集器的作用是删除不再引用/需要的对象,那么在没有垃圾收集器的环境中如何处理上述情况 - 比如C ++?

3 个答案:

答案 0 :(得分:4)

我认为这里没有真正的谜。

它不会“递归” - 你只是在托管堆上放一个新对象,它立即被解除引用;从而使其成为垃圾收集的候选者。

最终垃圾收集器将再次出现,再次触发操作等。

这不是递归 - 更像是一个链条。但最终每个Person都将从内存中删除。

过了一会儿,垃圾收集者会给你发一封电子邮件,抱怨你玩得不公平。

对于C ++,我的猜测是堆栈溢出,因为那时会发生构造/破坏,之后会出现一个非常生气的计算机。

如果您的下一个逻辑思维是'不应该运行时/语言阻止这种情况发生吗?' - 不。有问题的语言或运行时不能阻止你做一些本来被认为是不明智的事情;它信任你,程序员,以确保你没有这样做。

这就是说 - 在应用程序关闭场景(下面的评论)中.Net运行时将出于自身利益而最终停止处理这些终结器以实现关闭。终结器是为了您的利益,而不是运行时的。

答案 1 :(得分:2)

更有趣的一点是,对象在终结器中实际上可以resurrect itself

class Foo
{
    static public List<Foo> ZombieFoos = new List<Foo>;

    ~Foo()
    {
        ZombieFoos.Add(this);

        // Now there is a reference to this instance again (in the list)..
        // The GC will not reclaim this instance.. huzzah we have been resurrected!!
    }
}

甚至没有远程推荐...

答案 2 :(得分:1)

事实上,你可以在GC中使系统达到99.9次。只需通过每个Person对象获取足够的内存量,以便GC触发Heap 0集合。