Arrays, heap and stack and value types

2019-01-02 21:41发布

int[] myIntegers;
myIntegers = new int[100];

In the above code, is new int[100] generating the array on the heap? From what I've read on CLR via c#, the answer is yes. But what I can't understand, is what happens to the actual int's inside the array. As they are value types, I'd guess they'd have to be boxed, as I can, for example, pass myIntegers to other parts of the program and it'd clutter up the stack if they were left on it all the time. Or am I wrong? I'd guess they'd just be boxed and would live on the heap for as long the array existed.

8条回答
smile是对你的礼貌
2楼-- · 2019-01-02 22:27

Yes the array will be located on the heap.

The ints inside the array will not be boxed. Just because a value type exists on the heap, does not necessarily mean it will be boxed. Boxing will only occur when a value type, such as int, is assigned to a reference of type object.

For example

Does not box:

int i = 42;
myIntegers[0] = 42;

Boxes:

object i = 42;
object[] arr = new object[10];  // no boxing here 
arr[0] = 42;

You may also want to check out Eric's post on this subject:

查看更多
beautiful°
3楼-- · 2019-01-02 22:27

I think at the core of your question lies a misunderstanding about reference and value types. This is something probably every .NET and Java developer struggled with.

An array is just a list of values. If it's an array of a reference type (say a string[]) then the array is a list of references to various string objects on the heap, as a reference is the value of a reference type. Internally, these references are implemented as pointers to an address in memory. If you wish to visualize this, such an array would look like this in memory (on the heap):

[ 00000000, 00000000, 00000000, F8AB56AA ]

This is an array of string that contains 4 references to string objects on the heap (the numbers here are hexadecimal). Currently, only the last string actually points to anything (memory is initialized to all zero's when allocated), this array would basically be the result of this code in C#:

string[] strings = new string[4];
strings[3] = "something"; // the string was allocated at 0xF8AB56AA by the CLR

The above array would be in a 32 bit program. In a 64 bit program, the references would be twice as big (F8AB56AA would be 00000000F8AB56AA).

If you have an array of value types (say an int[]) then the array is a list of integers, as the value of a value type is the value itself (hence the name). The visualization of such an array would be this:

[ 00000000, 45FF32BB, 00000000, 00000000 ]

This is an array of 4 integers, where only the second int is assigned a value (to 1174352571, which is the decimal representation of that hexadecimal number) and the rest of the integers would be 0 (like I said, memory is initialized to zero and 00000000 in hexadecimal is 0 in decimal). The code that produced this array would be:

 int[] integers = new int[4];
 integers[1] = 1174352571; // integers[1] = 0x45FF32BB would be valid too

This int[] array would also be stored on the heap.

As another example, the memory of a short[4] array would look like this:

[ 0000, 0000, 0000, 0000 ]

As the value of a short is a 2 byte number.

Where a value type is stored, is just an implementation detail as Eric Lippert explains very well here, not inherent to the differences between value and reference types (which is difference in behavior).

When you pass something to a method (be that a reference type or a value type) then a copy of the value of the type is actually passed to the method. In the case of a reference type, the value is a reference (think of this as a pointer to a piece of memory, although that also is an implementation detail) and in the case of a value type, the value is the thing itself.

// Calling this method creates a copy of the *reference* to the string
// and a copy of the int itself, so copies of the *values*
void SomeMethod(string s, int i){}

Boxing only occurs if you convert a value type to a reference type. This code boxes:

object o = 5;
查看更多
登录 后发表回答