Generics memory management

后端 未结 7 710
慢半拍i
慢半拍i 2021-01-05 02:41

I have question regarding how memory is managed for strong type Generics

List ints1 = new List();
ints1.Add(1); ints1.Add(2); ints1.Add         


        
7条回答
  •  伪装坚强ぢ
    2021-01-05 03:14

    I presume as ints1 is initialised with a new keyword new List() it becomes a reference type

    This presumption is incorrect. You can use the "new" keyword on a value type too!

    int x = new int();
    

    Using "new" does not make anything a reference type. You can use "new" with reference types or value types. What "new" indicates is that storage is going to be allocated and a constructor is going to be called.

    In the case of using "new" on a value type, the allocated storage is temporary storage. A reference to that temporary storage is passed to the constructor, and then the now-initialized result is copied to its final destination, if there is one. ("new" is usually used with an assignment but it need not be.)

    In the case of a reference type, storage is allocated twice: long-term storage is allocated for the instance and short-term storage is allocated for the reference to long-term storage of the instance. The reference is passed to the constructor, which initializes the long-term storage. The reference is then copied from short-term storage to its final destination, if there is one.

    What makes List a reference type is that List is declared as a class.

    Where are the values 1,2,3 are stored in memory (are they stored in stack or on heap)?

    We've worked hard to make a memory manager that lets you not care where things are stored. Values are stored in either a short-term memory pool (implemented as the stack or registers) or a long-term memory pool (implemented as a garbage-collected heap). Storage is allocated depending on the known lifetime of the value. If the value is known to be short-lived then its storage is allocated on the short-term pool. If the value is not known to be short-lived then it must be allocated on the long-term pool.

    The 1, 2, 3 owned by the list could live forever; we do not know whether that list is going to outlive the current activation frame or not. Therefore the memory to store the 1, 2, 3 is allocated on the long-term pool.

    Do not believe the lie that "value types are always allocated on the stack". Obviously that cannot be true because then a class or array containing a number could not survive the current stack frame! Value types are allocated on the pool that makes sense for their known lifetime.

    List can scale its size to any size at runtime unlike int[]

    Correct. It is educational to see how List does that. It simply allocates an array of T larger than it needs. If it discovers that it guessed too small, it allocates a new, larger array and copies the old array contents to the new one. A List is just a convenient wrapper around a bunch of array copies!

    if the values 1,2,3 were stored in stack, and a new item 4 is added to the list, then it wouldn't be continuous to the first three.

    Correct. That's one reason why the storage for values 1, 2, 3 are not allocated on the stack. The storage is actually an array allocated on the heap.

    so how will the list know the memory location of item 4?

    The list allocates an array that is too big. When you add a new item, it sticks it into unused space in the too-big array. When the array runs out of room, it allocates a new array.

提交回复
热议问题