为何栈分配值类型Span<T>可封装.NET中的堆分配数组?
问题:既然Span本应是栈分配的值类型,它为何能封装堆分配的数组?
你查阅微软文档时看到以下内容:
当Span
封装数组时,它可以封装整个数组,正如Span与内存部分的示例所示。由于它支持切片,Span 也可以指向数组内的任意连续范围。
这看起来困惑的核心是混淆了Span<T>自身的存储位置和它所指向的数据的存储位置:
Span<T>作为ref struct,确实是分配在栈上的,但它本身并不存储实际的数据,本质上是一个安全的"内存视图包装器"。它内部仅包含三个关键信息:指向数据起始位置的指针、数据的长度、以及内存的边界校验信息。- 当它封装堆分配的数组时,栈上的
Span<T>实例只是持有了堆数组的内存起始地址,并没有把数组的内容拷贝到栈上。 Span<T>的设计目标就是提供对任意连续内存块的类型安全访问,不管这块内存位于栈、托管堆还是非托管内存区域。ref struct的限制只是防止Span<T>自身被分配到堆上(比如不能作为类的字段、不能在异步上下文里传递),但完全不影响它指向堆内存的能力——这和栈上的普通指针能指向堆内存是一个道理,只是Span<T>做了额外的安全校验,避免了裸指针的不安全操作。
内容的提问来源于stack exchange,提问作者Flint0fWalrus
相关产品推荐
相关产品推荐

