2011-12-10 52 views
4

C++代碼:在C#在C++中,指針的簡單迴歸安全/參考

person* NewPerson(void) 
{ 
    person p; 
    /* ... */ 
    return &p; //return pointer to person. 
} 

C#代碼:

person NewPerson() 
{ 
    return new person(); //return reference to person. 
} 

如果我沒有理解這一權利,在C++的例子也不行,因爲p將 超出範圍,並且該函數將返回一個野指針(懸掛指針)。

C#中的示例是可以的,因爲只要有引用,匿名新人就會保持在範圍內。 (呼叫功能得到一個。)

我收到了嗎?

+2

你是[比較蘋果與橙子!](http://thisisindexed.com/wp-content/uploads/2011/11/card3052-380x232.jpg) –

+1

也許,但它們都是水果。 :) – Niklas

回答

2
person* NewPerson(void) 
{ 
    person p(); 
    /* ... */ 
    return &p; //return pointer to person. 
} 

p不是person,看到most vexing parse。因此,你會得到一個編譯器錯誤。

其餘的,是的,你是對的。

1

在C++中,'p'將存在於堆棧中,因此當函數返回時會被破壞。在C#中,垃圾收集器知道不會破壞它,直到最後一個引用丟失。

(「撞」正在使用鬆散這裏...:P)

+0

是的,我不明白毆打:) – Niklas

+0

我應該更技術:)。我只是說它不再以有效的方式存在。在寫完之前,對象仍然存在於它所在的位置,但是一旦變量超出了作用域(在C++版本中),就不能保證(實際上它變得非常非常可能)對象很快就會被覆蓋。 – Corbin

2

本例中的作用域規則類似,但在C#如果返回值分配給的東西,那麼它不會被垃圾收集,只要因爲某些東西可以引用它。如果它沒有分配到的東西,沒什麼持有對它的引用,它會被垃圾收集下一次收集執行

0

我有這個對嗎?

是的。

BTW:in C++ person p();聲明一個函數並且不會調用人的默認ctor。只寫人p;

0

這在C++中不起作用,因爲您正在返回一個臨時對象的引用,該對象在函數結束後將被銷燬。您需要在堆上創建一個new人,然後返回對此的引用。

+0

除了人p()而不是人p-p的錯誤之外,它不是一個臨時對象(在C++中)。 – Simon

+0

對不起,你是正確的 - 我覺得現在我自己的回答是投票:O – Ell

1

是的,你說得對。

然而,在C++中,你會很喜歡這個

person NewPerson() 
{ 
    person p; 
    /* ... */ 
    return p; //return person. 
} 

,並相當肯定,在呼叫

person x = NewPerson(); 

編譯器將優化出來的返回值的複製。

+0

好的,但速度不會太快,對不對?因爲指針更快返回? (或許這是C++中的好選擇確實可以做分解函數) – Niklas

+0

在這種特殊情況下,該語言特別允許編譯器省略複製返回值並在'x'中構建它。大多數編譯器都會利用這一點。 –

+0

好的,所以它會有相同的速度,就像你返回一個指向新人的指針一樣? – Niklas

4

C++中的示例不正確,因爲'p'將超出範圍,並且該函數將返回無效指針。

正確。

C#中的示例是可以的,因爲只要有任何引用它,匿名'新人'就會保留在範圍內。

這或多或少是正確的,但您的術語並不完全正確。 範圍在C#中是文本的區域,其中不合格名稱可以使用。這裏的對象沒有名字。 使用期限運行期間,在此期間存儲位置保證有效。範圍和使用壽命相連;當控制離開與範圍相關的代碼時,通常允許在該範圍內聲明的本地人的生存期結束。 (有些情況下,當地人的壽命比控制範圍的時間長或短)

此外,請注意,它不是任何引用保持它活着的Person對象。該參考文件必須是根源爲。你可以有兩個相互引用的Person對象,否則它們是不可訪問的;每個人都有參考的事實並不能使他們活着;其中一個參考文獻必須根植於其中。