[英]Drawing a Path in XAML (with binding) vs. C#. One works, one doesn't
[英]Stackalloc vs. Fixed sized buffer in C#. What is the difference
就我而言,以下代碼將在堆棧上創建一個數組:
unsafe struct Foo
{
public fixed int bar[10];
}
var foo = new Foo();
stackalloc 語句會做同樣的事情:
public void unsafe foo(int length)
{
Span<int> bar = stackalloc int[length];
}
所以我想知道這些方法之間有什么區別。 還有固定大小緩沖區的目的是什么? 每個人都在談論性能提升,但我不明白為什么我需要它們,因為我已經可以使用 stackalloc 在堆棧上創建一個數組。 MSDN 說固定大小的緩沖區用於與其他平台“互操作”。 那么這個“互操作”是什么樣子的呢?
fixed
語句僅說明數組已內聯(固定在結構體內部)。 這意味着存儲在數組中的數據直接存儲在您的結構中。 在您的示例中, Foo
結構將具有存儲 10 個整數值所需的大小。 由於結構是值類型,因此它們被分配在堆棧上。 然而,它們也可以被復制到堆中,例如將它們存儲在引用類型中。
class Test1
{
private Foo Foo = new();
}
unsafe struct Foo
{
public fixed int bar[10];
}
上面的代碼將被編譯並且私有Foo
實例將存在於托管堆中。
如果沒有固定語句(只是一個“正常”的 int[]),數組的數據將不會存儲在結構本身中,而是存儲在堆中。 該結構將只擁有對該數組的引用。
使用stackalloc
,數據在堆棧上分配,不能由 CLR 自動移動到堆中。 這意味着堆棧分配的數據保留在堆棧上,編譯器將通過不允許這樣的代碼來強制執行此操作:
unsafe class Test1
{
// CS8345: Field or auto-implemented property cannot be of type 'Span<int>' unless it is an instance member of a ref struct.
private Span<int> mySpan;
public Test1()
{
// CS8353: A result of a stackalloc expression of type 'Span<int>' cannot be used in this context because it may be exposed outside of the containing method
mySpan = stackalloc int[10];
}
}
因此,當您絕對想確保分配的數據不能逃逸到堆中時,您可以使用stackalloc
,從而導致抓取收集器的壓力增加(這是一個性能問題)。 另一方面, fixed
主要用於與本機C/C++
庫的互操作場景,這些庫可能出於某種原因使用內聯緩沖區。 因此,當從本機世界調用將帶有內聯緩沖區的結構作為參數的方法時,您必須能夠在 .NET 中重新創建它,否則您將無法輕松使用本機代碼(因此存在fixed
語句)。 使用fixed
另一個原因是內聯結構中的數據,這可以在 CPU 訪問它時進行更好的緩存,因為它可以一次性讀取Foo
中的所有數據,而無需取消引用引用並在內存中跳轉訪問存儲在別處的一些數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.