gpt4 book ai didi

c# - 为什么 stackalloc 不能与引用类型一起使用?

转载 作者:太空狗 更新时间:2023-10-29 18:26:38 29 4
gpt4 key购买 nike

如果 stackalloc 与引用类型一起使用,如下所示

var arr = stackalloc string[100];

有错误

Cannot take the address of, get the size of, or declare a pointer to a managed type ('string')

为什么会这样?为什么 CLR 不能声明指向托管类型的指针?

最佳答案

.NET 中的即时编译器在将 C# 编译器生成的 MSIL 转换为可执行机器代码时执行两项重要任务。显而易见的是生成机器代码。不明显且完全不可见的工作是生成一个表,该表告诉垃圾收集器在执行方法时发生 GC 时在哪里查找对象引用。

这是必要的,因为对象根不能作为类的字段仅存储在 GC 堆中,存储在局部变量或 CPU 寄存器中。为了正确地完成这项工作,抖动需要知道堆栈帧的确切结构和存储在那里的变量的类型,以便它可以正确地创建该表。这样,稍后垃圾收集器就可以弄清楚如何读取正确的堆栈帧偏移量或 CPU 寄存器来获取对象根值。指向 GC 堆的指针。

当您使用 stackalloc 时,这是一个问题。该语法利用了允许程序声明自定义值类型的 CLR 功能。围绕正常托管类型声明的后门,限制是此值类型不能包含任何字段。只是一 block 内存,由程序生成适当的偏移量到该 block 中。 C# 编译器可帮助您根据类型声明和索引表达式生成这些偏移量。

在 C++/CLI 程序中也很常见,相同的自定义值类型功能可以为 native C++ 对象提供存储。只需要存储该对象的空间,如何正确初始化它并访问该 C++ 对象的成员是 C++ 编译器解决的工作。 GC 无需了解任何内容。

所以核心限制是无法为这 block 内存提供类型信息。就 CLR 而言,这些只是没有结构的普通字节,GC 使用的表没有描述其内部结构的选项。

不可避免地,您唯一可以使用的类型是不需要 GC 需要了解的对象引用的类型。 Blittable 值类型或指针。所以 System.String 不行,它是一个引用类型。您可能得到的最接近“粘稠”的是:

  char** mem = stackalloc char*[100];

进一步的限制是,确保 char* 元素指向固定或非托管字符串完全取决于您。而且你不会索引“数组”越界。这不是很实用。

关于c# - 为什么 stackalloc 不能与引用类型一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35598078/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com