至于我在c#中讀到的發送關鍵字,會改變引數。那么這兩種情況有什么不同:
用完:
helper(out param){...} func(){ int param = 0; helper(out param)}使用指標:
helper(int* param){..} func(){ int param = 0; helper(¶m)}
他們一樣嗎?恩克斯。
uj5u.com熱心網友回復:
用例與關鍵字名稱所暗示的不同。
out 是 C# 中的一個關鍵字,用于將引數作為參考型別傳遞給方法。通常在一個方法回傳多個值時使用。out 引數不傳遞該屬性。
C# 中的指標,用于通過參考傳遞引數。或者我們可以說,如果在方法中對這個引數進行了任何更改,那么當控制元件回傳到呼叫方法時,指標將反映在該變數中。
指標通常用于與 C 互操作,不會在日常 C# 編碼中使用。我們可以使用 ref 型別。
uj5u.com熱心網友回復:
這兩件事在概念上是相似的。這里的主要區別是:
int*是一個非托管指標ref int是一個托管指標out int實際上只是ref int在確定分配周圍有一些額外的編譯器防護欄
那么:托管指標和非托管指標有什么區別?主要區別:
- GC 可以正確跟蹤托管指標
- 這意味著您無需在使用之前固定/修復某些東西
- 因此你不需要使用
unsafe - 它更可驗證
- 和更多人理解代碼
反過來:
- 您可以將非托管指標存盤在型別的欄位中(托管指標只能保存在堆疊中)
- 但是如果那個非托管指標指向已經移動/消失的東西:BOOM
所以:在任何可以使用托管指標(ref或out)代替未管理指標的情況下:您應該. 老實說,很少有 C# 開發人員完全了解托管指標的細微差別,但完全了解未管理指標的細微差別的就更少了。
uj5u.com熱心網友回復:
當然,在更高級別上,unsafe代碼的實作方式存在差異,因此您只能使用指向原始型別的指標,而使用out關鍵字可以將任何型別指定為引數。
但有趣的是,看看兩者在較低級別的匯編代碼中有何不同。
考慮最小骨架代碼。
static class Program
{
static unsafe void Main(string[] args)
{
int x;
SetArg(out x);
Console.WriteLine(x);
int y;
SetArg(&y);
Console.WriteLine(y);
}
static void SetArg(out int x)
{
x = 10;
}
static unsafe void SetArg(int* ptr)
{
*ptr = 10;
}
}
以及行內的結果匯編代碼
SetArg(out x);
00007FFD4EB80890 int 3
00007FFD4EB80891 sub esp,28h
00007FFD4EB80894 xor eax,eax
00007FFD4EB80896 mov dword ptr [rsp 24h],eax
Console.WriteLine(x);
00007FFD4EB8089A mov ecx,0Ah ! case a)
00007FFD4EB8089F call 00007FFDAA4E2890
int y;
SetArg(&y);
00007FFD4EB808A4 lea rcx,[rsp 24h]
00007FFD4EB808A9 mov dword ptr [rcx],0Ah ! case b)
Console.WriteLine(y);
00007FFD4EB808AF mov ecx,dword ptr [rsp 24h]
00007FFD4EB808B3 call 00007FFDAA4E2890
00007FFD4EB808B8 nop
00007FFD4EB808B9 add rsp,28h
00007FFD4EB808BD ret
在out陳述句的第一種情況下,值在被函式寫入控制臺之前10 = 0Ah直接寫入暫存器。這是超級優化的,因為在此操作中不使用記憶體。這就是為什么不建議對代碼進行微優化,而只用關鍵字傳達意圖并讓編譯器完成其作業的原因。ecxWriteline()ref/out
在帶有int*引數的第二種情況下,值10 = 0Ah被寫入堆疊上與函式引數對應的記憶體地址,然后ecx在呼叫之前從該地址加載Writeline()。這里的代碼不僅不安全,而且優化程度也較低,因為程式員強迫編譯器在使用前將中間值存盤在堆疊中。
注意不是的替代定義SetArg()是
static unsafe void SetArg(int* ptr)
{
ptr[0] = 10; // same as ptr* = 10
}
但這凸顯了另一個潛在問題。緩沖區溢位,或越界記憶體訪問,因為如果你寫了
ptr[-1] = 10;
或除ptr[0]預期記憶體位置之外的任何其他內容,那么您已經損壞了導致 havok 的行程記憶體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/376743.html
標籤:C#
上一篇:如何從“<name>_<fileNum>of<fileNumTotal>”或“<name>”形式的檔案名中提取名稱?
