Original:---C # heap vs Stack (part)
Objective
In the first article in this series, C # stack contrast (Part One), the basic functions and value types of the stack and the performance of the reference type in the program runtime are described, as well as the explanation of the pointer action.
This article is the second part of the article, mainly on the role of parameters in the stack.
Note: limited to my English comprehension skills, as well as technical experience, if there is a mistake in the text, please do not hesitate to point out.
Directory
C # Stack contrast (Part one)
C # Stack Contrast ( part of )
C # Stack contrast (Part three)
C # Stack contrast (Part Four)
Key issues---parameter discussion
This is what happens when we execute the code. In the first step we've covered what happens when we call the method, so let's take a look at more details ...
When we call the method, the following things will happen:
- When we execute a method, we need to create a space on the stack. This contains the address call (pointer) of a goto instruction, so when the thread finishes executing our method, it knows how to go back and continue executing the program.
- The parameters of our method will be copied. This is what we have to study carefully.
- Control is passed to the JIT ' Ted method and the thread starts executing code. Hence, we have another method represented by a stack frame on the ' Call stack '.
Code snippet:
Public int Addfive (int pValue) { int result; 5 ; return result;}
The stack will be like this:
Note: The method is not really on the stack, here is just an example to illustrate.
As we discussed in part one, the parameters on the stack will be handled in different ways, depending on whether it is a value type or a reference type. The value type is the copy copy, and the reference type is passed in the reference itself. (A value types is copied over and the reference of A reference type are copied Over.ed over.)
Note: The value type is a fully copied (copied) object, the value of the new object is changed or not and the original value is affected; The reference type copies only pointers to types, sharing the same object in memory.
Value type delivery
Below we will discuss value types ...
First, when we pass the value type, the space will be created and will copy our type to a new space in the stack, let's analyze the following code:
class class1{ publicvoid Go () { int5; Addfive (x); Console.WriteLine (X.tostring ()); } Public int Addfive (int pValue) { 5; return pValue; } }
At the beginning of the execution of the program, the variable x=5 is allocated a space on the stack, such as:
Next, Addfive () carries its parameters on the stack, and the parameters are copied from the variable x in a byte-by-byte, such as:
When the Addfive () method finishes executing, the thread (pointer entry) will go to the Go () method and, because the Addfive () method has been completed, Pvalue will naturally be recycled, such as:
Note: Here the thread pointer is rolled back to the go method after the TEMP variable pvalue will be reclaimed, that is, the gray module in.
So, the correct output is 5, right? The point is that any value type is passed as a parameter to a method when a full copy copy (carbon copy) is made and the value of the original variable is saved without being affected (we count on the original variable's value to be Preserved.).
What we must remember is that if we have a very large value type (such as a large struct) and pass it as a parameter to the method, it will be copied each time and will take a lot of memory and CPU time. The space of the stack is limited, just like pouring water from a faucet into a cup, it always overflows. Structs are value types and can be very large, which we must pay attention to when we use them.
Note: The structure can be understood here as a value type, when it is passed as a parameter to the method, it is necessary to copy copies, so if the structure of space, it will inevitably lead to space and memory efficiency problems, this must be paid attention to.
The following is a very large structure:
Public struct mystruct{ long A, B, C, D, E, F, G, H, I, J, K, L, M;}
Next, let's look at what happens when the Go method is executed:
Public void Go () { new mystruct (); DoSomething (x); } Public void dosomething (MyStruct pValue) { // do SOMETHINGhere ...}
It would be very inefficient. Imagine that if we pass 12,000 times, you can understand why efficiency is so low.
So, how do we get around this problem? The answer is to pass a reference that points to a value type. As shown below:
Public void Go () { new mystruct (); DoSomething (ref x); Public struct mystruct{ longpublicvoid dosomething (ref mystruct PValue) { // do SOMETHINGhere ...}
Thus, we will use memory efficiently after referencing the struct body by ref.
When we pass a value type in a reference way, we only need to focus on the change in value type values. Pvalue change, then x changes at the same time. With the following code, the result will be "12345", because pvalue depends on the memory space represented by X.
Public void Go () { new mystruct (); 5 ; DoSomething (ref x); Console.WriteLine (X.a.tostring ()); Public void DoSomething (ref mystruct pValue) { 12345;}
Passing reference types
The passing of a reference type is similar to the way a wrapper value type is referenced, as mentioned earlier in this example.
If we use reference types:
Public class myint{ publicint myvalue;}
And calling the Go method, the Myint object is eventually on the heap because it is a reference type:
Public void Go () { new MyInt (); }
If we execute the Go method as follows:
Public void Go () { new MyInt (); 2 ; DoSomething (x); Console.WriteLine (X.myvalue.tostring ()); Public void dosomething (MyInt pValue) { 12345;}
- Start executing the Go method, and the variable x enters the stack.
- Executes the DoSomething method, and the parameter pvalue into the stack.
- The value of X (the Myint address on the stack) is passed to Pvalue.
So, when we change the pvalue in the heap and we call X again, we get "12345". myvalue
This is a very interesting place. What happens when a reference type is passed in a referenced manner?
Discuss it carefully. If we have "Objects" (Thing Class), animals, vegetables, these kinds of things:
Public class Public class animal:thing{ publicint publicclass vegetable:thing{ publicint Length;}
Then we execute the Go method as follows:
Public voidGo () {Thing x=NewAnimal (); Switcharoo (refx); Console.WriteLine ("x is Animal:"+ (x isAnimal). ToString ()); Console.WriteLine ("x is vegetable:"+ (x isvegetable). ToString ()); } Public voidSwitcharoo (refThing PValue) {PValue=Newvegetable ();}
Then we get the following result:
X is Animal:false
X is Vegetable:true
Next, let's see what happens, such as:
- Start execution of the Go method, and the X pointer is initialized on the stack.
- The animal type is created on the heap.
- Begins the execution of the Switchroo method, Pvalue is created on the stack and points to the X
4. The vegetable class is created on the heap.
5. Change the x pointer and point to the vegetable type.
If we do not pass the "thing" (Thing) with the ref keyword, we will keep animal and get the result that we want to reverse from the code.
If you don't understand the above code, refer to my type reference paragraph to better understand how the reference type works.
Note: When declaring a parameter with the REF keyword, the reference type passes a pointer to the reference type, whereas if there is no ref keyword, the parameter passes a new pointer (reference) to the reference content. In the author's example, when the REF keyword is present, the X (pointer) is passed, and if the Swtichroo method does not use the REF keyword, it actually points directly to animal.
Readers can remove the ref keyword, compile it, and output the result:
x is Animal : True
X is vegetable: False
The answer is the opposite of the original.
Summarize
Part A is concerned about the difference in memory when the parameter is passed, and in the next section, let's look at the reference variable on the stack and overcome some of the problems that arise when we copy the object.
1. value type when the parameter is copied, the copy is a new object on a stack, which is recycled after use.
2. the value type when the parameter, the copy phenomenon, so for some "very large" structure type will have a very serious efficiency problem, you can try to use the REF keyword to wrap the structure into a reference type for delivery, saving space and time.
3. a reference type passes a reference address, which means that multiple things point to the same block of memory, and if changing the value in memory will feed back to all of the objects it references.
4. the Ref keyword passes a pointer to a reference type, not a reference type address.
---C # heap vs Stack (part)