Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Are Arrays of Structs Value Type or Eeference Type Objects?

Discussion in 'Scripting' started by garv3, Aug 17, 2018.

  1. garv3

    garv3

    Joined:
    Dec 30, 2012
    Posts:
    32
    So we know that all structs are value types. For example a Vector3 is a struct and therfore a value type variable.
    But what about arrays of structs? Will they be on the stack or the heap?

    This is a bad idea for sure:
    Code (CSharp):
    1. void Update()
    2. {
    3.     GameObject go = new GameObject();
    4.     ... Do some stuff with 'go'
    5. }
    Because GameObject is a class, this will allocate heap memory every frame and the garbage collector is going to be very busy and slow down the game.

    This on the other hand is pretty much okay:
    Code (CSharp):
    1. void Update()
    2. {
    3.     Vector3 position = new Vector3(1,1,1);
    4.     ... Do some stuff with 'position'
    5. }
    Since Vector3 is a struct this will allocate memory on the stack, which is not such a big deal as allocating on the heap because it will be freed as soon as the functio ends and the garbage collector won't even know the variable existed.

    But what about this:
    Code (CSharp):
    1. void Update()
    2. {
    3.     Vector3[] positions = new Vector3[100];
    4.     ... Do some stuff with 'positions'
    5. }
    Vector3 is a struct (=value type), but is Vector[] a struct as well or will this allocate memory on the heap?

    Who knows this for sure?
    Thanks in advance!
    garv3
     
    Last edited: Aug 17, 2018
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,146
  3. garv3

    garv3

    Joined:
    Dec 30, 2012
    Posts:
    32
    Great, thx!

    What about structs that contain instances of classes?
    From what I understand they will have to allocate heap memory too, right? But how can we know, which struct contains class instances? It is impossible to track every struct down all the way...
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    Nope!

    You're not allocating anything there. The GameObject in aPublicVariable is already allocated, so you're just messing with already allocated memory. Since it's a reference type, you're not allocating anything new, you're just creating a temporary reference to the same GameObject on the stack.

    The same goes for your array example, taking a reference to an existing array isn't going to allocate anything. If you make a new array, that's an allocation. You're not making a new array in your example.
     
  5. garv3

    garv3

    Joined:
    Dec 30, 2012
    Posts:
    32
    Okay, yeah... The examples were not correct. Edited the initial post. Now it should be obvious, what I mean.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    Right.

    So, yeah, creating a new array of a struct definitely allocates on the heap, as pointed out earlier. For your later question:

    No, they won't. A struct is always a value type. They're not allocated to the heap. If they contain a class instance as a field, that class is on the heap (unless it's null). So there's heap memory involved, but the struct itself doesn't cause any allocations.

    Structs that contains references to classes are often useful. A good example is RaycastHit - it's a struct, but "contain" classes - like the collider that was hit. It should be obvious that the RaycastHit doesn't allocate that collider on the heap, it just contains a reference to the pre-allocated collider.
     
  7. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    I don't know if this helps, but try thinking about using arrays in generic functions like so:
    T[] array = new T[100];


    This forces you to think more cleanly about the difference between the array and whatever the T type is. The array is a container that contains a certain amount of T objects. It doesn't really matter what T is, the container is what needs to take up heap space.

    Now, if you're asking about how much memory an array will allocate, well that's a different story.

    If T is a reference type, then the size of the array is "array length * sizeof(reference)", where the size of a reference is basically the size of a pointer depending on your OS.

    If T is a value type, then the size of the array is "array length * sizeof(T)".

    There's a nice illustration of that in the selected answer here: https://stackoverflow.com/questions...ation-for-an-array-of-struct-and-class-object
     
  8. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    As mentioned in my previous post, references are basically pointers. A pointer is an int that represents the memory address of where ever the object exists in memory. Or it could be 0 to represent NULL.

    So if your struct contains nothing but reference types, then it's basically a struct of ints. In order for an object to exist, you'll need to create it, get a reference to it, then store the reference in the struct.

    Think of it as a book that lists home addresses -- the book doesn't contain homes, it just contains addresses that tell you where to find a home you're looking for.