2017-08-24 206 views
-1

比方说,你有这样的:(样板代码遗漏)在函数内部声明用作返回值的对象时会发生什么?为什么他们不能在退货上取消分配?

static Object foo() 
{ 
    Object test = new Object(); 
    return test; 
} 

Object output = foo(); 

至少在C#中,程序不会当您尝试使用即使它指向foo中声明的同一对象输出崩溃。为什么它不立即得到解除分配? 如果这是处理Object返回值的不好的方法,有没有更好的方法来处理它?

+1

“为什么它不立即得到解除分配?”由于垃圾收集,我们正在传递引用。 C#中的爱永远不必说你已经完成了。 –

+0

“C#中的爱永远不必说你完成了。” - 这很深@JeroenMostert:D Ken:通过将参考分配给'output',对函数内创建的对象有强烈的引用。这就是为什么GC不会收集它。为什么这会是“处理对象返回值的不好方法”?你还会如何返回一个引用类型? – Fildor

+2

反过来,为什么*应该*程序崩溃?这不是很清楚你想在这里做什么?您是否希望程序崩溃,因为您没有明确告诉它制作适合在函数外部访问的副本?你想知道堆栈上到底有什么,以及堆栈上的每一点都有什么?如果您说“是”,那么您可以拥有C程序员的美好职业 - 但您(大多数人)在编程C#时不需要携带那些精神包袱。 –

回答

0

参考通过。对象是一个引用类型,意味着对它进行的每一个变化(包括分配)都将保存在声明了该对象的块中。

如果你做了一些C/C++,引用有些自动管理的指针。

返回这是不错的做法,但应该小心它。当您返回引用并稍后分配它时,如果您之前已经分配过该引用,则会丢失以前的版本。同样,如果你做了一些C,就像将指针指向第二个分配的内存部分,留下第一个(在前面的例子中)。

2

GC将只收集(如果它选择)没有可达引用的对象。在您的例子:

static object foo() 
{ 
    object test = new object(); 
    return test; 
} 

object output = foo(); 

通过test引用的实例也被outputfoo返回引用。因此,即使test不再是可达参考,因此,其“指向”的实例仍不是收集的候选。

下面的例子是完全不同的:

static object foo() 
{ 
    object test = new object(); 
    return test; 
} 

foo(); 

这里,test引用的实例是收集一次foo返回一个有效的候选人(或甚至之前,但让我们忽略了这些优化),因为一旦foo返回,没有可达到的对象的引用。

请注意,我使用可达参考。一个对象可能有引用它的有效引用,但如果包含该引用的对象也是收集的候选者,它仍然是收集的候选对象。 GC对于这些类型的周期足够智能:

class A { public B b; } 
class B { public A a; } 

void Foo() 
{ 
    A a = new A(); 
    B b = new B(); 
    a.B = b; 
    b.A = a; 
} 

Foo(); //both a and b are elegible for collection once Foo exists. 
相关问题