[ACCEPTED]-Why are structs stored on the stack while classes get stored on the heap(.NET)?-.net
(edited to cover points in comments)
To emphasise: there 16 are differences and similarities between 15 value-types and reference-types, but those 14 differences have nothing to do with stack vs heap, and 13 everything to do with copy-semantics vs 12 reference-semantics. In particular, if we 11 do:
Foo first = new Foo { Bar = 123 };
Foo second = first;
Then are "first" and "second" talking 10 about the same copy of Foo
? or different copies? It 9 just so happens that the stack is a convenient 8 and efficient way of handling value-types as variables. But 7 that is an implementation detail.
(end edit)
Re 6 the whole "value types go on the stack" thing... - value 5 types don't always go on the stack;
- if they are fields on a class
- if they are boxed
- if they are "captured variables"
- if they are in an iterator block
then they 4 go on the heap (the last two are actually 3 just exotic examples of the first)
i.e.
class Foo {
int i; // on the heap
}
static void Foo() {
int i = 0; // on the heap due to capture
// ...
Action act = delegate {Console.WriteLine(i);};
}
static IEnumerable<int> Foo() {
int i = 0; // on the heap to do iterator block
//
yield return i;
}
Additionally, Eric 2 Lippert (as already noted) has an excellent blog entry on this 1 subject
It's useful in practice to be able to allocate 6 memory on the stack for some purposes, since 5 those allocations are very fast.
However, it's 4 worth noting that there's no fundamental 3 guarantee that all structs will be placed 2 on the stack. Eric Lippert recently wrote 1 an interesting blog entry on this topic.
That's a great question; I did not cover 2 it in the article that Marc Gravell linked 1 to. Here's part two:
Every process has a data block consists 14 of two different allocatable memory segment. These 13 are stack and heap. Stack is mostly serving 12 as the program flow manager and saves local 11 variables, parameters and returning pointers 10 (in a case of returning from the current 9 working function).
Classes are very complex 8 and mostly very large types compared to 7 value types like structs (or basic types 6 -- ints, chars, etc.) Since stack allocation 5 should be specialized on the efficiency 4 of program flow, it is not serving an optimal 3 environment to keep large objects.
Therefore, to 2 greet both of the expectations, this seperated 1 architecture came along.
In some languages, like C++, objects are 13 also value types.
To find an example for 12 the opposite is harder, but under classic 11 Pascal union structs could only be instantiated 10 on the heap. (normal structs could be static)
In 9 short: this situation is a choice, not a 8 hard law. Since C# (and Java before it) lack 7 procedural underpinnings, one can ask themselves 6 why it needs structures at all.
The reason 5 it is there, is probably a combination of 4 needing it for external interfaces and to 3 have a performant and tight complex (container-) type. One 2 that is faster than class. And then it is 1 better to make it a value type.
How the compiler and run-time environment 28 handle memory management has grown up over 27 a long period of time. The stack memory 26 v.s. heap memory allocation decision had a 25 lot to do with what could be known at compile-time 24 and what could be known at runtime. This 23 was before managed run times.
In general, the 22 compiler has very good control of what's 21 on the stack, it gets to decide what is 20 cleaned up and when based on calling conventions. The 19 heap on the other hand, was more like the 18 wild west. The compiler did not have good 17 control of when things came and went. By 16 placing function arguments on the stack, the 15 compiler is able to make a scope -- that scope 14 can be controlled over the lifetime of the 13 call. This is a natural place to put value 12 types, because they are easy to control 11 as opposed to reference types that can hand 10 out memory locations (pointers) to just 9 about anyone they want.
Modern memory management 8 changes a lot of this. The .NET runtime 7 can take control of reference types and 6 the managed heap through complex garbage 5 collection and memory management algorithms. This is also a very, very deep subject.
I 4 recommend you check out some texts on compilers 3 -- I grew up on Aho, so I recommend that. You can also 2 learn a lot about the subject by reading 1 Gosling.
Marc Gravell already explained wonderfully 57 the difference regarding how value and reference 56 types are copied which is the main differentiation 55 between them.
As to why value types are usually 54 created on the stack, that's because the 53 way they are copied allows it. The stack 52 has some definite advantages over the heap 51 in terms of performance, particularly because 50 the compiler can calculate the exact position 49 of a variable created in a certain block 48 of code, which makes access faster.
When 47 you create a reference type you receive 46 a reference to the actual object which exists 45 in the heap. There is a small level of indirection 44 whenever you interact with the object itself. These 43 reference types cannot be created on the 42 stack because the lifetime of values in 41 the stack is determined, in great part, by 40 the structure of your code. The function 39 frame of a method call will be popped off 38 the stack when the function returns, for 37 example.
With value types, however, their 36 copy semantics allows the compiler, depending 35 on where it was created, to place it in 34 the stack. If you create a local variable 33 that holds an instance of a struct in a 32 method and then return it, a copy of it 31 will be created, as Marc explained above. This 30 means that the value can be safely placed 29 in the stack, since the lifetime of the 28 actual instance is tied to the method's 27 function frame. Anytime you send it somewhere 26 outside the current function a copy of it 25 will be created, so it doesn't matter if 24 you tie the existence of the original instance 23 to the scope of the function. Along these 22 lines, you can also see why value types 21 that are captured by closures need to go 20 in the heap: They outlive their scope because 19 they must also be accessible from within 18 the closure, which can be passed around 17 freely.
If it were a reference type, then 16 you wouldn't be returning a copy of the 15 object, but rather a reference, which means 14 the actual value must be stored somewhere 13 else, otherwise, if you returned the reference 12 and the object's lifetime was tied to the 11 scope in which it was created, it would 10 end up pointing to an empty space in memory.
The 9 distinction isn't really that "Value types 8 go on the stack, reference types on the 7 heap". The real point is that it's usually 6 more efficient to access objects that live 5 in the stack, so the compiler will try and 4 place those values it can there. It simply 3 turns out that value types, because of their 2 copy semantics, fit the bill better than 1 reference types.
I believe that whether or not to use stack 3 or heap space is the main distinction between 2 the two, perhaps this article will shed 1 some light on your question: Csharp classes vs structs
The main difference being that the heap 10 may hold objects that live forever while 9 something on the stack is temporary in that 8 it will disappear when the enclosing callsite 7 is exited. This is because when one enters 6 a method it grows to hold local variables 5 as well as the caller method. When the method 4 exits (ab)normally eg return or because 3 of exception each frame must be popped off 2 the stack. Eventually the interested frame 1 is popped and everything on it lost.
The whole point about using the stack is 33 that it automatically implements and honours 32 scope. A variable stored on the stack exists 31 until the functiont that created it exits 30 and that functions stack frame is popped. Things 29 that have local scope are natural for stack 28 storage things that have bigger scope are 27 more difficult to manage on the stack. Objects 26 on the heap can have lifetimes that are 25 controlled in more complex ways.
Compilers 24 always use the stack for variables - value 23 or reference it makes little difference. A 22 reference variable doesn't have to have 21 its value stored on the stack - it can be 20 anywhere and the heap makes a more efficient 19 if the object referenced is big and if there 18 are multiple references to it. The point 17 is that the scope of a reference variable 16 isn't the same as the lifetime of the object 15 it references i.e. a variable may be destroyed 14 by being popped off the stack but the object 13 (on the heap) it references might live on.
If 12 a value type is small enough you might as 11 well store it on the stack in place of a 10 reference to it on the heap - its lifetime 9 is tied to the scope of the variable. If 8 the value type is part of a larger reference 7 type then it too could have multiple references 6 to it and hence it is more natural to store 5 it on the heap and dissociate its lifetime 4 from any single reference variable.
Stack 3 and heap are about lifetimes and the value 2 v reference semantics is almost a by product.
Have 1 a look at Value and Reference
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.