C#7.0中引用返回的值是否存储在堆栈或堆中?

Dan*_*aar 2 c# clr

由于引入了C#7.0的引用返回功能,并且根据我的理解,这样的功能需要在编译器上进行一些重新布线才能将此引用仅存储在堆上的变量上,是否可以存储返回的引用到堆栈上的变量,或者新的ref声明是否确保变量始终存储在堆上?

ref int x = ref DoSomething(data); 
// Is the value of x now on the stack or the heap? Or is x stored on the stack as a reference and the value on the heap?
Run Code Online (Sandbox Code Playgroud)

我的理解基于这篇文章:

最后,CLR确实允许"ref return类型"; 理论上你可以使用一个方法"ref int M(){...}"返回对整数变量的引用.如果由于某些奇怪的原因我们决定在C#中允许它,我们必须修复编译器和验证器,以便它们确保只能将refs返回到已知在堆上的变量,或者已知在堆栈上"低于"比被叫者更低.

Eri*_*ert 10

这首歌的名字叫做"Haddocks'Eyes"."哦,这就是这首歌的名字,是吗?" 爱丽丝说,试着感兴趣."不,你不明白,"骑士说,看起来有些烦恼."这就是这个名字的名字.这个名字真的是"老年人"."那么我应该说"这就是这首歌的名字"?爱丽丝纠正自己."不,你不应该:那是另一回事!这首歌被称为"方式和手段":但这只是它的名字,你知道!"那么,那首歌是什么?" 爱丽丝说,他此时已经完全不知所措了."我来了,"骑士说."这首歌真的是"A-sitting On a Gate":这首曲子是我自己的发明.

歌曲,歌曲的名称,名称的名称以及歌曲的名称显然都是不同的.


有三件事你不能混淆:

  • 变量引用的位置- 别名.
  • 引用变量的位置- 别名变量.
  • 如果引用变量是引用类型,则引用的事物的位置(如果有).

ref int x = ref DoSomething(data); 
Run Code Online (Sandbox Code Playgroud)

x的值现在是堆栈还是堆?

表达式x另一个变量别名.

该变量具有值.

假设别名变量是值类型.是别名变量,因此它的值是临时池(也称为"堆栈")还是长期池("堆")?我们不知道.我们也不关心.我们知道无论哪个,我们都保证这个变量现在还活着.

但是我们可以猜测:ref返回的变量通常是堆分配变量的别名,因为我们确定它们是活着的.

假设别名变量是引用类型.被引用存储在堆栈或堆中的?同样,我们也不知道,出于同样的原因.是该引用的指示堆栈或堆中的?它可以在堆上,也可以为null; 我们保证了这一点.

或者x是否作为参考存储在堆栈上并且堆上的值?

通过x你的意思的变量x别名,或你的意思是当地的x本身?本地本身存储在堆栈或寄存器中; 它永远不会被提升到封闭类的领域.变量别名可以在任何地方,但如上所述,很可能在堆上.


Han*_*ant 7

ref int xint* x变量在运行时的行为方式的语法糖.将变量作为参数传递给方法并声明参数时,您获得的行为完全相同ref,调用者将指针传递给变量.指针不关心值的存储位置,实际上可以存储在任何地方.请注意,您无法传递属性,它没有存储空间.

他们在C#v7中必须做的非常重要的事情是确保你不会意外地创建一个悬空指针错误.在C和C++等语言中臭名昭着,在这些语言中它是未定义的行为,不需要编译器生成诊断.很多带有该bug的程序似乎运行得很好,直到程序中看似微不足道的变化(添加函数调用)破坏了指向的值.

实际上并不难做afaik,被调用方法的局部变量是麻烦制造者.方法返回后它们不再存在,因此引用变为无效.在C#v7中将给出编译错误的特定方案.但是,如果局部变量是调用者之一,它很好,并且它通过参数传入引用,该变量仍然存活.