C#使用stackalloc分配堆棧內(nèi)存和非托管類型詳解
stackalloc 表達式
stackalloc表達式在棧(stack)上分配內(nèi)存塊。
在方法執(zhí)行期間創(chuàng)建的棧中分配的內(nèi)存塊會在方法返回時自動丟棄。不能顯式釋放使用 stackalloc 分配的內(nèi)存。stackalloc分配的內(nèi)存塊不受垃圾回收的影響,也不必通過 fixed 語句固定。
棧內(nèi)存,棧內(nèi)存開辟快速高效但資源有限,通常限制1M。
可以將 stackalloc 表達式的結(jié)果分配給以下任一類型的變量:
stackalloc 分配 System.Span<T> 或 System.ReadOnlySpan<T> 類型
int length = 3;
Span<int> numbers = stackalloc int[length];
for (var i = 0; i < length; i++)
{
numbers[i] = i;
}
將stack分配內(nèi)存塊賦值給 System.Span<T> 或 System.ReadOnlySpan<T> 類型的變量不必使用不安全上下文(unsafe context)。
可以在表達式允許的任何地方使用stackalloc,并且在需要分配內(nèi)存時,推薦盡可能的使用 Span<T> 或 ReadOnlySpan<T> 類型。
int length = 1000; Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
Console.WriteLine(ind); // output: 1
stackalloc 分配 指針類型
如下示例,對于指針類型,stackalloc表達式只能用于本地變量聲明的初始化中。
unsafe
{
int length = 3;
int* numbers = stackalloc int[length];
for (var i = 0; i < length; i++)
{
numbers[i] = i;
}
}
使用指針類型,必須使用不安全上下文(unsafe context)。
stackalloc分配內(nèi)存的注意點
堆??捎玫膬?nèi)存數(shù)量是有限的,如果分配太多內(nèi)存,則可能發(fā)生StackOverflowException異常。因此需要注意以下幾點:
- 限制使用
stackalloc分配的內(nèi)存數(shù)量。
例如,如果預期的緩沖區(qū)大小低于某個限制,則可以在堆棧上分配內(nèi)存;否則,請使用所需長度的數(shù)組。如下代碼所示:
const int MaxStackLimit = 1024; Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];
stack 上可用內(nèi)存數(shù)量取決于代碼的執(zhí)行環(huán)境。
- 避免在循環(huán)內(nèi)部使用
stackalloc。在循環(huán)外部allocate分配內(nèi)存塊,并在循環(huán)內(nèi)部重用。
新分配內(nèi)存的內(nèi)容是未定義的。必須在使用之前初始化。 比如,可以使用 Span<T>.Clear 方法設(shè)置所有的元素項為類型T的默認值。
也可以使用數(shù)組初始化器定義新分配內(nèi)存的內(nèi)容。
Span<int> first = stackalloc int[3] { 1, 2, 3 };
Span<int> second = stackalloc int[] { 1, 2, 3 };
ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };
非托管類型 Unmanaged type
在定義指針、stackalloc T[n]時,其類型只能是非托管類型。(雖然在使用和形式上,非托管類型與C#的原始類型幾乎沒有區(qū)別,但,還是可以了解下)。
以下類型的屬于或也屬于非托管類型:
sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal, orbool- 任何
enum類型 - 任何
pointer類型 - 任何 只包含非托管類型字段的用戶定義(
user-defined)的struct類型
使用非托管泛型約束unmanaged,指定類型參數(shù)為非指針、不可為空的非托管類型。
僅包含非托管類型字段的構(gòu)造結(jié)構(gòu)類型(constructed struct type)也是非托管的。如下示例所示,DisplaySize<T>()方法的泛型約束為unmanaged,在調(diào)用時Coords<int>、Coords<double>作為非托管類型使用:
using System;
public struct Coords<T>
{
public T X;
public T Y;
}
public class UnmanagedTypes
{
public static void Main()
{
DisplaySize<Coords<int>>();
DisplaySize<Coords<double>>();
}
private unsafe static void DisplaySize<T>() where T : unmanaged
{
Console.WriteLine($"{typeof(T)} is unmanaged and its size is {sizeof(T)} bytes");
}
}
// Output:
// Coords`1[System.Int32] is unmanaged and its size is 8 bytes
// Coords`1[System.Double] is unmanaged and its size is 16 bytes
泛型結(jié)構(gòu)Coords<T>可以是非托管和托管構(gòu)造類型。當然也可以限制為非托管類型,如下:
public struct Coords<T> where T : unmanaged
{
public T X;
public T Y;
}
參考
以上就是C#使用stackalloc分配堆棧內(nèi)存和非托管類型詳解的詳細內(nèi)容,更多關(guān)于C# stackalloc分配堆棧內(nèi)存的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#獲取Excel文件所有文本數(shù)據(jù)內(nèi)容的示例代碼
獲取上傳的?EXCEL?文件的所有文本信息并存儲到數(shù)據(jù)庫里,可以進一步實現(xiàn)對文件內(nèi)容資料關(guān)鍵字查詢的全文檢索,有助于我們定位相關(guān)文檔,本文詳細介紹了C#獲取Excel文件所有文本數(shù)據(jù)內(nèi)容實現(xiàn)步驟和代碼,需要的朋友可以參考下2024-07-07
.net使用Aspose.Words進行Word替換操作的實現(xiàn)代碼
之前在工作中,需要實現(xiàn)Word打印功能,并且插入圖片。當時采取的方式則是使用書簽進行操作。首先在word內(nèi)插入書簽,完成后,存為模板。程序加載該模板,找到書簽,并在指定位置寫入文字即可2013-05-05
C#基礎(chǔ):Equals()與運算符==的區(qū)別分析
本篇文章是對c#中的Equals()與運算符==的區(qū)別進行了詳細的分析介紹,需要的朋友參考下2013-05-05

