2017-08-24 236 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. 
相關問題