6*)
“Where” is a really indeterminate term when it comes to managed code. There’s where in all of known available memory you might be… which honestly, you don’t need to know that. That’s some bare metal coding to know that. You technically CAN get that information if you really really wanted it, but you probably won’t need to. This though is honestly stuff you won’t really ever need, and you can go look into in more depth on your own time just for knowledge sake.
What you may want to know is the “general” where of in memory .Net/mono places things in managed memory (managed memory meaning .net/mono deals with the WHERE things are in memory for you so you don’t have to really care about it…). It splits the memory it allocates for itself into two parts.
The ‘stack’ and the ‘heap’.
When you call ‘new’ on a class, because it’s a class, a chunk of the ‘heap’ is allocated for that specific object. That’s where the actual object will exist. Whenever you need to access this object you need a “reference” to the object in the heap. Quite literally it’s an integer that represents a index (sort of…) within the heap. You honestly NEVER see this value, and the way it is organized is dependent on .net/mono and is subject to change in any update of the runtime. What you do know is that this ‘reference’ is represented as the ‘variable’ you’ve made for it.
MyClass obj; //<- this is a variable with a null reference right now, it points at nothing
obj = new MyClass(); //you just created an instance of MyClass and a reference to it is assigned to 'obj'
var obj2 = obj; //the same reference that obj is, is now set to obj2. obj and obj2 point to the same object on the heap
References may exist as members of an object as fields (the variables that are members directly of the class), or in operating code on the stack as parameters or variables scoped to a function.
The stack is the chunk of memory that handles all the memory that is currently being operated on directly. Think of it like if you were cooking and while cooking you had the recipe right there in front of you. You don’t really store the entire recipe all in your active thinking memory in your head, you let it rest there on the paper until you get to that step of the recipe. Only then you read the information you need and operate on that. 1 cup sugar, pour in bowl. 2 cups water, pour in bowl. etc etc.
Here’s more information about the stack and heap.
I didn’t really read this, just grabbed the first article I saw that looked reasonable when I googled it.
I will add this… you will hear people say that ‘value types’ (structures: int, float, Vector3) ALWAYS exist on the stack, unless otherwise boxed and placed on the 'heap. There is a lot of misconception about what constitutes boxing. I will say… no…
Value types exist directly where you place them, and aren’t referenced (unless otherwise explicitly stated as referenced with the ‘ref’ keyword). So that variable you create, instead of storing an integer that points to where on the ‘heap’ you’re value is, it’s just that value instead. If that variable is scoped to a function (like a parameter), then yes, it’s on the stack. But if that variable is a field on a class, then the value exists on the heap as a member of the object it is a field on. Of course when you go and access that variable in operating code, a copy is brought to the stack to be operated on. This is why a lot of the time when dealing with ‘structs’ you have copy a value out very explicitly and copy it back in. This is why you have to do things like this:
//doesn't work
someGameObject.transform.position.y += 5f;
//does work
var pos = someGameObject.transform.position;
pos.y += 5f;
someGameObject.transform.position = pos;