Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#7.0中通过引用返回的值是否存储在堆栈或堆中?_C#_Clr - Fatal编程技术网

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

C#7.0中通过引用返回的值是否存储在堆栈或堆中?,c#,clr,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

由于引入了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?
我的理解基于:

最后,CLR允许“ref返回类型”;理论上你可以 有一个方法“ref int M(){…}”,该方法返回对 整数变量。如果出于某种奇怪的原因我们决定允许 在C#中,我们必须修复编译器和验证器,以便 确保只能将引用返回到 已知在堆上,或已知在堆栈上“较低” 而不是被叫人

这首歌的名字叫“哈多克斯的眼睛” “哦,这就是这首歌的名字,是吗?”爱丽丝说,试图表现出兴趣。 “不,你不明白,”骑士说,看起来有点恼火这就是它的名字。这个名字真的是“老人” “那么我应该说“这就是这首歌的名字”?”爱丽丝纠正了自己。 “不,你不应该这样,那完全是另一回事了!这首歌叫做“方式和方法”:但你知道,那只是它的名字 “那么,这首歌是什么?”爱丽丝说,这时她完全不知所措了。 “我正打算这么做,”骑士说这首歌真的是“坐在门上”:这首曲子是我自己的发明

这首歌,这首歌的名字,名字叫什么,这首歌叫什么,显然都不一样


有三件事你不能混淆:

  • 变量引用的位置--别名
  • 引用变量的位置--别名变量
  • 如果引用的变量为引用类型,则引用对象的位置(如有)

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

表达式
x
是另一个变量的别名

该变量有一个值

假设别名变量是值类型。别名变量及其值是在临时池(也称为“堆栈”)还是在长期池(称为“堆”)上?我们不知道。我们也不在乎。我们知道,无论它是什么,我们都可以保证这个变量现在是活动的

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

假设别名变量为引用类型。引用存储在堆栈还是堆上?同样,出于同样的原因,我们也不知道。该引用的引用对象是在堆栈上还是在堆上?它要么在堆上,要么为null;我们对此有保证

或者x作为引用和堆上的值存储在堆栈上

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?

通过
x
您是指
x
别名的变量,还是指本地
x
本身?本地数据本身存储在堆栈或寄存器中;不得将其吊至封闭类场地。别名的变量可能在任何地方,但如上所述,很可能在堆上。

ref int x
int*x
的语法糖,即变量在运行时的行为方式。当您将变量作为参数传递给方法并且参数声明为
ref
时,调用者会传递指向该变量的指针,这与您得到的行为完全相同。指针不关心值存储在哪里,实际上可以存储在任何地方。请注意,您不能传递属性,它没有存储空间

他们在C#v7中必须做的一件非常重要的事情是确保您不会意外地创建一个。像C和C++这样的语言臭名昭著,它是那些没有编译器要求生成诊断的语言中的未定义行为。许多带有该缺陷的程序似乎运行得很好,直到程序中看似微不足道的更改(添加函数调用)破坏了指向的值


实际上并不难,被调用方法的局部变量是麻烦制造者。方法返回后,它们不再存在,因此引用无效。在C#v7中会出现编译错误的特定场景。但是如果局部变量是调用方之一,并且它通过参数传入引用,则可以,该变量仍处于活动状态。

如果它是局部变量,则它将在堆栈上等待sure@EhsanSajjad如果它只是一个局部变量,那么你就不能从
ref
返回方法返回它。你能详细说明一下你说@Servy是什么意思吗?@EhsanSajjad自己试试看。它不会编译,编译器错误将或多或少地告诉您我告诉您的内容。如果您可以从ref返回方法返回对局部变量的引用,那么您将拥有对范围外变量的引用,而C#不允许这样做。您从Eric引用的内容回答了您的问题。返回的引用需要是对堆中某个值的引用,或者是对堆栈上更高的值的引用。也可以是,我喜欢你的答案。但C#7如何确保变量在创建别名时处于活动状态?我现在无法尝试,但在同一个方法中返回对局部变量(堆栈上)的引用是否有效?@illdans4:编译器必须跟踪每个引用的来源和发生的情况。将我们知道是本地的ref返回给本地的ref是不合法的。在所有情况下都可以这样做吗?如果在另一个已经编译的程序集中有一个ref-returning-ref-taking方法,该方法只返回提供给它的引用,该怎么办?即使在这种情况下,编译器也会检查方法吗?@illdans4:好问题。全部d