views:

1128

answers:

11

I know that one of the differences between classes and structs is that struct instances get stored on stack and class instances(objects) are stored on the heap.

Since classes and structs are very similar. Does anybody know the difference for this particular distinction?

+7  A: 

It's useful in practice to be able to allocate memory on the stack for some purposes, since those allocations are very fast.

However, it's worth noting that there's no fundamental guarantee that all structs will be placed on the stack. Eric Lippert recently wrote an interesting blog entry on this topic.

mquander
The relative speeds of the allocations are not particularly relevant. It's the *deallocation* that is cheap on the stack. Deallocation of a value on the stack is done by moving the stack pointer, which takes about a nanosecond. Deallocation of a value on the heap requires a garbage collection, which can take arbitrarily long.
Eric Lippert
Wow, thanks for the clarification, which makes obvious sense when I think about how it actually works. I'll remember that.
mquander
A: 

I believe that whether or not to use stack or heap space is the main distinction between the two, perhaps this article will shed some light on your question: Csharp classes vs structs

Dortz
Actually, the distinction value-type/reference-type is more fundamental, imo.
Rik
+4  A: 

Every process has a data block consists of two different allocatable memory segment. These are stack and heap. Stack is mostly serving as the program flow manager and saves local variables, parameters and returning pointers (in a case of returning from the current working function).

Classes are very complex and mostly very large types compared to value types like structs (or basic types -- ints, chars, etc.) Since stack allocation should be specialized on the efficiency of program flow, it is not serving an optimal environment to keep large objects.

Therefore, to greet both of the expectations, this seperated architecture came along.

Burcu Dogan
I like your response. Very informative +1
Jose Basilio
.Net applications and most other applications have a stack and a heap, but, not all programs have of a stack and heap. For example stackless python doesn't have a stack at all. It uses a link list of heap allocated frames for method calls...
Pop Catalin
This is a .NET related question. The only reason that I used "every".
Burcu Dogan
A: 

Value types go on the stack, reference types go on the heap. A struct is a value type.

There is no guaruantee about this in the specification though, so it might change in future releases:)

Andomar
Value types do *not* always go on the stack
Marc Gravell
Just giving the rule of thumb (without writing "always") There's no rule that says reference types have to go on the heap either :-)
Andomar
The problem is that this statement (oft repeated) is the root cause of a **lot** of confusion; it is a: inaccurate, and b: irrelevent. I don't mean that negatively (I know how long that line has been in circulation!) - I just don't thinks it helps anyone to repeat it ;-p
Marc Gravell
The OP is asking why classes are typically on the heap, and structs typically on the stack. A rule-of-thumb answer might be more helpful than advanced talk about captured variables ;)
Andomar
Where did the OP use the word "typically"? No, it seems to me that repeating this myth is *not* a good idea, particularly when you don't give any indication in the answer that *isn't* always the case. If I make a statement such as: "String literals are interned in C#" surely there's an implicit "always" there, isn't there? Your "rule of thumb" isn't nearly as helpful as the accurate answer, in my experience. Once people understand the difference between a variable storing a reference and it storing the value itself, the stack/heap stuff is much more obvious, but less relevant.
Jon Skeet
But the rule of thumb is very, very wrong. They are asking a question (already based on a misconception) to *increase* their knowledge. How would giving them an incorrect answer be useful, especially if it re-inforces the existing misunderstanding?
Marc Gravell
I'm just trying to keep it simple. If a new programmer asks about stack/heap, chances are he's really asking about value/reference. I try to avoid mentioning closures, captured variables, and iterators, which can only confuse people that are trying to grasp reference/value. I can see your point though.
Andomar
So don't mention those things, but don't propagate the myth either. Correct it.
Jon Skeet
+19  A: 

(edited to cover points in comments)

To emphasise: there are differences and similarities between value-types and reference-types, but those differences have nothing to do with stack vs heap, and everything to do with copy-semantics vs reference-semantics. In particular, if we do:

Foo first = new Foo { Bar = 123 };
Foo second = foo;

Then are "first" and "second" talking about the same copy of Foo? or different copies? It just so happens that the stack is a convenient and efficient way of handling value-types as variables. But that is an implementation detail.

(end edit)

Re the whole "value types go on the stack" thing... - value 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 go on the heap (the last two are actually 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 Lippert (as already noted) has an excellent blog entry on this subject

Marc Gravell
This is a great answer, but I don't think it addresses why if structs and classes are very similar, they get treated differently when it comes to the heap and the stack.
ichiban
I'm not sure they are "very similar" - but the point is; the differences between them have very little to do with stack and heap, and everything to do with copy-semantics vs reference-semantics
Marc Gravell
+1  A: 

In some languages, like C++, objects are also value types.

To find an example for the opposite is harder, but under classic Pascal union structs could only be instantiated on the heap. (normal structs could be static)

In short: this situation is a choice, not a hard law. Since C# (and Java before it) lack procedural underpinnings, one can ask themselves why it needs structures at all.

The reason it is there, is probably a combination of needing it for external interfaces and to have a performant and tight complex (container-) type. One that is faster than class. And then it is better to make it a value type.

Marco van de Voort
+1  A: 

How the compiler and run-time environment handle memory management has grown up over a long period of time. The stack memory v.s. heap memory allocation decision had a lot to do with what could be known at compile-time and what could be known at runtime. This was before managed run times.

In general, the compiler has very good control of what's on the stack, it gets to decide what is cleaned up and when based on calling conventions. The heap on the other hand, was more like the wild west. The compiler did not have good control of when things came and went. By placing function arguments on the stack, the compiler is able to make a scope -- that scope can be controlled over the lifetime of the call. This is a natural place to put value types, because they are easy to control as opposed to reference types that can hand out memory locations (pointers) to just about anyone they want.

Modern memory management changes a lot of this. The .NET runtime can take control of reference types and the managed heap through complex garbage collection and memory management algorithms. This is also a very, very deep subject.

I recommend you check out some texts on compilers -- I grew up on Aho, so I recommend that. You can also learn a lot about the subject by reading Gosling.

JP Alioto
A: 

The main difference being that the heap may hold objects that live forever while something on the stack is temporary in that it will disappear when the enclosing callsite is exited. This is because when one enters a method it grows to hold local variables as well as the caller method. When the method exits (ab)normally eg return or because of exception each frame must be popped off the stack. Eventually the interested frame is popped and everything on it lost.

mP
+1  A: 

Marc Gravell already explained wonderfully the difference regarding how value and reference types are copied which is the main differentiation between them.

As to why value types are usually created on the stack, that's because the way they are copied allows it. The stack has some definite advantages over the heap in terms of performance, particularly because the compiler can calculate the exact position of a variable created in a certain block of code, which makes access faster.

When you create a reference type you receive a reference to the actual object which exists in the heap. There is a small level of indirection whenever you interact with the object itself. These reference types cannot be created on the stack because the lifetime of values in the stack is determined, in great part, by the structure of your code. The function frame of a method call will be popped off the stack when the function returns, for example.

With value types, however, their copy semantics allows the compiler, depending on where it was created, to place it in the stack. If you create a local variable that holds an instance of a struct in a method and then return it, a copy of it will be created, as Marc explained above. This means that the value can be safely placed in the stack, since the lifetime of the actual instance is tied to the method's function frame. Anytime you send it somewhere outside the current function a copy of it will be created, so it doesn't matter if you tie the existence of the original instance to the scope of the function. Along these lines, you can also see why value types that are captured by closures need to go in the heap: They outlive their scope because they must also be accessible from within the closure, which can be passed around freely.

If it were a reference type, then you wouldn't be returning a copy of the object, but rather a reference, which means the actual value must be stored somewhere else, otherwise, if you returned the reference and the object's lifetime was tied to the scope in which it was created, it would end up pointing to an empty space in memory.

The distinction isn't really that "Value types go on the stack, reference types on the heap". The real point is that it's usually more efficient to access objects that live in the stack, so the compiler will try and place those values it can there. It simply turns out that value types, because of their copy semantics, fit the bill better than reference types.

jrcalzada
+6  A: 

That's a great question; I did not cover it in the article that Marc Gravell linked to. Here's part two:

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

Eric Lippert
A: 

The whole point about using the stack is that it automatically implements and honours scope. A variable stored on the stack exists until the functiont that created it exits and that functions stack frame is popped. Things that have local scope are natural for stack storage things that have bigger scope are more difficult to manage on the stack. Objects on the heap can have lifetimes that are controlled in more complex ways.

Compilers always use the stack for variables - value or reference it makes little difference. A reference variable doesn't have to have its value stored on the stack - it can be anywhere and the heap makes a more efficient if the object referenced is big and if there are multiple references to it. The point is that the scope of a reference variable isn't the same as the lifetime of the object it references i.e. a variable may be destroyed by being popped off the stack but the object (on the heap) it references might live on.

If a value type is small enough you might as well store it on the stack in place of a reference to it on the heap - its lifetime is tied to the scope of the variable. If the value type is part of a larger reference type then it too could have multiple references to it and hence it is more natural to store it on the heap and dissociate its lifetime from any single reference variable.

Stack and heap are about lifetimes and the value v reference semantics is almost a by product.

Have a look at Value and Reference

mikej