分配给引用类型变量的 pointer/reference 的隐藏值是多少?
What is the hidden value of the pointer/reference assigned to reference type variables?
int number = 1
number的值为1,因为它是值类型
分配给引用类型变量的指针的实际值是多少?
是整数还是字符串?或者它是一些比特?如果你把它写出来会是什么样子?是否可以使用该值分配对变量的引用?
Question harrysQuestion = new Question();
harrysQuestion 只是对新问题的指针或引用。那么该指针的值是多少?如果我这样做,分配给另一个问题变量的相同值:
Question harrysQuestionAgain = harrysQuestion;
它是指向我计算机内存中某个位置的数字吗?它是幕后实际的 C# 值变量吗?
Is it a number that points to some position in my computers memory?
从概念上讲,引用和指针是分开但相关的。实际上,它们 virtually 可以互换,区别在于 GC 知道如何遍历和修复引用(垃圾 collection 等),但不知道指针(还有其他关于fixed
如何在值的 hack 方面工作,允许在堆栈上找到的引用 value 被廉价地解释为 "pinned")。实际上,它们在所有实现中 非常接近 each-other(出于性能原因),您可以将它们视为 kinda一样。
您实际上想要获取引用的"value"(而不是解除引用),并且除非您首先固定 object,否则您需要非常小心,因为地址可能会更改(并且指针版本 不会被更正 )。对于这个 use-case 的需求实际上 增加 即将到来的 "pipelines" 工作,因此 Unsafe
实用程序类型的 corefxlab / myget 版本实际上提供了一些促进引用/指针交换的方法(包括内部 pointers/references 到 objects),但是:除非你正在做一些低级别的事情,否则你可能永远不需要它。
每个请求(评论):我提到了 "pinning" 和 "fixed" - 这里的问题是 .NET 有一个 "compacting" 垃圾收集器,允许 在运行时将 object 移动到 附近,只要它承诺修复所有引用 和 确保您永远不会从托管代码中注意到这一点。它不承诺的是修复指针。所以:如果您要将任何 object 视为指针 ,您需要告诉运行时(尤其是:垃圾收集器)根本不要移动 object,或者至少在您告诉它您完成之前。这就是 "pinning" 的意思。 "pin"有两种方式:
- 用于 long-term 引脚(通常是像
byte[]
缓冲区这样的东西,您将作为字段存储在 object 中并作为指针传递给非托管代码),您可以对 object 使用 GCHandle
,它会记录在 GC 知道要查看的全局结构中
- 对于 在堆栈上 的引用的 short-term 引脚,
fixed
关键字做了一些让 GC(总是查看每个stack) 知道引用 - 因此 object 被引用到 (该地址的 object ) - 应该被认为是固定的, 没有 需要不断地 add/remove 到全局结构
作为一个可能有趣的旁注:"interior references" 和对值类型的引用是一个概念 仅存在于堆栈上 - 而不是 字段 在可能最终出现在堆上的类型上(这意味着任何 class
或 struct
除了新的 ref struct
概念)。它们的工作方式与常规引用相同,但这些引用的目标是 内容本身 ,而不是 object header 的开头。这意味着
var fieldReference = ref this._someField;
或
SomeOtherMethod(ref this._someField);
或
SomeOtherMethod(ref someArray[index]);
在方法内部工作只要内部引用仅在堆栈上(即没有 async
/ yield
/ captured-variables / ETC); GC 乐于承担解析指向 objects 的内部指针的开销,但仅针对堆栈 - 以减少所涉及工作的总体规模。
int number = 1
number的值为1,因为它是值类型
分配给引用类型变量的指针的实际值是多少?
是整数还是字符串?或者它是一些比特?如果你把它写出来会是什么样子?是否可以使用该值分配对变量的引用?
Question harrysQuestion = new Question();
harrysQuestion 只是对新问题的指针或引用。那么该指针的值是多少?如果我这样做,分配给另一个问题变量的相同值:
Question harrysQuestionAgain = harrysQuestion;
它是指向我计算机内存中某个位置的数字吗?它是幕后实际的 C# 值变量吗?
Is it a number that points to some position in my computers memory?
从概念上讲,引用和指针是分开但相关的。实际上,它们 virtually 可以互换,区别在于 GC 知道如何遍历和修复引用(垃圾 collection 等),但不知道指针(还有其他关于fixed
如何在值的 hack 方面工作,允许在堆栈上找到的引用 value 被廉价地解释为 "pinned")。实际上,它们在所有实现中 非常接近 each-other(出于性能原因),您可以将它们视为 kinda一样。
您实际上想要获取引用的"value"(而不是解除引用),并且除非您首先固定 object,否则您需要非常小心,因为地址可能会更改(并且指针版本 不会被更正 )。对于这个 use-case 的需求实际上 增加 即将到来的 "pipelines" 工作,因此 Unsafe
实用程序类型的 corefxlab / myget 版本实际上提供了一些促进引用/指针交换的方法(包括内部 pointers/references 到 objects),但是:除非你正在做一些低级别的事情,否则你可能永远不需要它。
每个请求(评论):我提到了 "pinning" 和 "fixed" - 这里的问题是 .NET 有一个 "compacting" 垃圾收集器,允许 在运行时将 object 移动到 附近,只要它承诺修复所有引用 和 确保您永远不会从托管代码中注意到这一点。它不承诺的是修复指针。所以:如果您要将任何 object 视为指针 ,您需要告诉运行时(尤其是:垃圾收集器)根本不要移动 object,或者至少在您告诉它您完成之前。这就是 "pinning" 的意思。 "pin"有两种方式:
- 用于 long-term 引脚(通常是像
byte[]
缓冲区这样的东西,您将作为字段存储在 object 中并作为指针传递给非托管代码),您可以对 object 使用GCHandle
,它会记录在 GC 知道要查看的全局结构中 - 对于 在堆栈上 的引用的 short-term 引脚,
fixed
关键字做了一些让 GC(总是查看每个stack) 知道引用 - 因此 object 被引用到 (该地址的 object ) - 应该被认为是固定的, 没有 需要不断地 add/remove 到全局结构
作为一个可能有趣的旁注:"interior references" 和对值类型的引用是一个概念 仅存在于堆栈上 - 而不是 字段 在可能最终出现在堆上的类型上(这意味着任何 class
或 struct
除了新的 ref struct
概念)。它们的工作方式与常规引用相同,但这些引用的目标是 内容本身 ,而不是 object header 的开头。这意味着
var fieldReference = ref this._someField;
或
SomeOtherMethod(ref this._someField);
或
SomeOtherMethod(ref someArray[index]);
在方法内部工作只要内部引用仅在堆栈上(即没有 async
/ yield
/ captured-variables / ETC); GC 乐于承担解析指向 objects 的内部指针的开销,但仅针对堆栈 - 以减少所涉及工作的总体规模。