C# 结构值类型

C# 结构值类型,c#,.net,C#,.net,我知道struct是一种值类型,这意味着它是在堆栈上定义的 但是我可以做一个A=新的A();(当然是我的结构)。它定义在堆上,只有引用变量在堆栈上 你能给我解释一下这个吗。你的代码(A=newa();)创建并初始化了结构。如果是局部变量,则在堆栈上初始化。如果它是一个成员变量,它将作为对象的一部分在堆上初始化。在C#/.NET中使用“new”并不一定意味着堆分配。这取决于上下文 但是我可以做一个A=新的A();(当然是我的结构)。它定义在堆上,只有引用变量在堆栈上 如果A如您所说是一种值类型,并

我知道struct是一种值类型,这意味着它是在堆栈上定义的

但是我可以做一个A=新的A();(当然是我的结构)。它定义在堆上,只有引用变量在堆栈上

你能给我解释一下这个吗。

你的代码(A=newa();)创建并初始化了结构。如果是局部变量,则在堆栈上初始化。如果它是一个成员变量,它将作为对象的一部分在堆上初始化。在C#/.NET中使用“new”并不一定意味着堆分配。这取决于上下文

但是我可以做一个A=新的A();(当然是我的结构)。它定义在堆上,只有引用变量在堆栈上

如果
A
如您所说是一种值类型,并且
A
是一种本地方法,那么它将被分配到堆栈上。除非在闭包中使用
a
,否则它将作为编译器生成的类的堆分配对象的一部分进行分配


如果需要进一步分析,则必须发布
A
类型的定义以及定义此变量的整个方法。

值类型有时存储在堆栈上。这是一个复杂的主题,通常变量(堆栈或堆)的确切存储与编程问题无关。值类型和引用类型之间的真正区别在于它们的行为(例如,值类型总是按值复制)

Eric Lippert详细介绍了该问题:


最初认为值类型存在于“堆栈上”的假设是不正确的。然而,Eric Lippert透露,

  • 这通常是错误的:语句应该是“值类型可以存储在堆栈上”,而不是更常见的“值类型总是存储在堆栈上”
  • 这几乎总是无关紧要的。我们一直在努力创建一个托管环境,在这个环境中,不同类型的存储之间的区别对用户来说是隐藏的。与某些语言不同,在这些语言中,出于正确性原因,您必须知道特定存储是在堆栈上还是在堆上
  • 这是不完整的。推荐信呢?引用既不是值类型,也不是引用类型的实例,而是值。它们必须被存放在某个地方。它们是在堆栈上还是堆上?为什么从来没有人谈论他们?仅仅因为它们在C#type系统中没有类型,就没有理由忽略它们

  • 存储局部变量的地方是实现细节。
    简单的局部变量通常存储在CPU寄存器和/或堆栈中

    如果它们在闭包中被捕获,它们将被重写为堆分配对象中的成员。这是因为lamda可能比它创建的函数更长寿,因此它使用的变量也必须足够长

    <>与C++中的C++不同,<强> >代码>新< /代码>并不意味着堆分配< /强>。这只是调用构造函数的语法

    对值类型调用
    new
    ,也没有新位置的语义。它的语义是在某处构造一个实例,然后将其复制到目标变量中

    在我的心智模型中,有两种类型的存储:

  • 无法超过函数返回时间的本地存储。这包括堆栈和寄存器
  • 在不再引用之前一直存在的全局存储。这通常是堆。但是在进行转义分析的运行时,如果运行时证明没有引用会在函数中存活,则可能会将其放在堆栈上

  • 您的示例属于第一类存储,因为您使用的是值类型。

    a a=new a()
    从概念上构造结构的新实例并将其复制到a中。当然,编译器可以对其进行优化。除非编译器能够保证在单线程代码中不能观察到这一点,否则它不会就地构造。对于成员变量,它通常不能。@Jason-是的,变量a可能是闭包的一部分,并由编译器提升。这条皱纹似乎超出了提问者的要求。正如我所说,它取决于上下文。使用
    new
    实例化结构不会改变结构的存储方式或内存分配方式
    new
    并不自动意味着它正在堆上分配内存。@Jim是对的。“new”不是指“在堆上分配”,而是指“适当地分配,然后运行适当的构造函数”。如何分配内存取决于运行时。