I was planning to create a TIN Triangle network program some time ago. The idea was to split and merge the process, establish a balanced binary tree, then build and merge Subtrees, and then add them to my father's point set. Since I am familiar with the. net language, I am ready to use the c # language for implementation. However, I have never heard that when the created type is only used to store data, it is best to use the structure as the value type, and use the class to affect performance. Think about the Node where I create a binary tree first. I only need a vertex set and a pointer to the left and right child nodes, which is expressed as follows in c ++: struct Node {char c; Node * lChind; node * rChild;} This structure can be easily established in a certain language such as C ++, but it is quite troublesome for c. C # and other non-finger languages do not directly support pointer types. When values are assigned between different types, values are copied. This function is referenced only when function parameters have keywords ref or out, how can we conveniently implement the value type pointer function. For more information, see c #. net. Here we first give a c # implementation method of the above structure: unsafe struct Node {public char c; Node * lChild; Node * rChild; public Node (char value_ch) {c = value_ch; lChild = null; rChild = null;} public Node * LChild {get {return lChild;} set {lChild = value ;}} public Node * RChild {get {return rChild ;} set {rChild = value ;}} public override string ToString () {string s = "value:" + c; if (lChild! = Null) s + = "," + "left child node value:" + lChild-> c; if (rChild! = Null) s + = "," + "right child node value:" + rChild-> c; return s ;}} the unsafe keyword supports the following usage: 1. define unsafe class (unsafe class class_name {}) 2 define unsafe fields of the class 3. defines the insecure structure (unsafe struct {}). The structure defined above is an insecure structure. 4. Define an insecure method, whether it is a static method, a virtual method, or an instance method. 5. Define Insecure code segments (.... safe code... unsafe {.... insecure code segment ...}.... safe code ...) everyone knows.. net platform supports the garbage collection function, which provides a garbage collector. The total number of c # types is the value type and reference type. The Spam collector is responsible for releasing the reference type (the actual type is managed), which largely solves the problem of c, memory leakage and rewriting in c ++ and other languages .. The memory management system of the NET platform allocates value types on the stack, from the high address to the low address during allocation, and the reference type is allocated on the stack. During allocation, the value types are allocated from the low address to the high address. The code segment defined below illustrates this problem: unsafe {int x, y, z; byte m = 199; int n = 200; x = 5; y = 10; z = 15; int * _ p = & x; Console. writeLine ("x address: {0}", (uint) _ p); Console. writeLine ("_ p address: {0})", (uint) & _ p); _ p --; Console. writeLine ("y address: {0}, _ p value: {1}", (uint) & y, (uint) _ p); _ p --; Console. writeLine ("z address: {0}, _ p value: {1}", (uint) & z, (uint) _ p); _ p --; Console. writeLine ("m address: {0}, _ p value: {1}", (uint) & m, (uint) _ p); _ p --; Console. writeLine ("The address of n is {0}, the value of _ p is {1}", (uint) & n, (uint) _ p);} Here x, y, z, m, n, and an integer pointer Variable _ p. Then output their addresses. From the running result (here I use decimal to indicate the address), we can see that the addresses of these six variables are reduced in turn, each variable occupies four bytes of memory (int is stored in the continuous space of the 32-bit processor stack, not all data types are continuously allocated on the stack ). The pointer is essentially an integer, but this integer represents an address in the memory (32 is 0 ~ 4 billion), we can use uint to integer the address. At the same time, a pointer operation is involved. pointer _ p points to x first, and then minus 1 (actually minus sizeof (data type )), as we mentioned above, the memory allocation in the stack is from the high to the bottom, and the Pointer Points to y. From the result, we can see that the address of y is the same as the value of _ p; what happens if we point _ p plus 1 to memory 81783252? No one knows what will happen. If we assign a value to the memory, it may overwrite the memory used by other programs, or it may be a simple memory value with no memory. There is another problem above. The m variable is of the byte type. In theory, it occupies one byte memory. Why does it occupy four bytes of memory (81783236 ~ 81783232? The reason is that the 32-bit processor is best at getting data from 4-byte memory blocks, and the memory on this machine is divided into 4-byte blocks, for the next allocation, the stack pointer points to the beginning of a 4-byte memory block. net decides to allocate memory on the stack as a multiple of 4 (I am not very clear here, I am also a beginner at school, please do not look into it here ), therefore, the byte type is allocated 4 bytes of space. When the scope of these variables is reached, the value of the stack pointer increases sequentially, which is equivalent to deleting these local variables. This is not the case for the reference type. Variables (pointers) of the reference type are still stored on the stack. The occupied space is 4 bytes, and the actual objects are stored on the stack, the deletion of referenced variables and the deletion of referenced objects are not synchronized, which leads to memory holes in the stack. Many objects are saved in the heap, And the Garbage Collector maintains information about these objects, such as the number of object references and memory address. When the garbage collector is running, because of the non-synchronous deletion problem mentioned above, the objects with 0 references will be deleted here, and there will be a memory hole (in many cases, when our programs use unmanaged resources, such as network connections, database connections, and file connections, we need to manually release the memory occupied by these resources, it is good to implement the IDispose interface by making these classes that use unmanaged resources ). The next time you allocate memory for a new object on the heap, you must scan until you find a memory block that matches the size. This will inevitably increase the time it takes to instantiate an object and reduce the program performance. However, the garbage collector cannot make the heap appear in this situation. It sorts the memory after the garbage collection is completed, and moves the remaining objects to the end (to the lower address ), let the heap pointer point to the first empty memory of the heap, and allocate space for the object from here when the object is instantiated next time. Although this takes some time, compared with the previous case, microsoft believes that performance can be improved a lot. At the same time, this also causes a problem, that is, the pointer to the class field is invalid. Therefore, generally, c # does not allow the declaration of the pointer to the class field, this is caused by the movement of the heap object. However, with the fixed keyword, we can lock the object and declare a pointer to the class field. For example, unsafe {Program pro = new Program (); fixed (int * p_id = & (pro. id), p_age = & (pro. age) fixed (double * p_salary = & (pro. salary )){..... add code .....}} the preceding two integer pointers, one double precision pointer, point to several fields in the Program class respectively. Structure of High-performance arrays. C # specifies that the array is of the reference type, so it is allocated to the stack, which is different from that of c ++. the array of c ++ is of the value type and is allocated to the stack. Stack access is very fast. In a program that frequently accesses an array, assigning the array to the stack can improve program performance. The stackalloc keyword can be used to implement this function, as shown in the following code: unsafe {double * p_nodes = stackalloc double [20]; int * p_ages = stackalloc int [20];} the above two 20-sized arrays are declared on the stack, and the k elements of the array can be accessed through * (p + k) or p [k. Well, the pointer function in. net is actually very simple, mainly because when we use it. For example, when we read an image, we can only use the pointer function, which can speed up reading. In other cases, use it with caution, because the unsafe keyword may appear in multiple places of the entire program, which is difficult to maintain and manage, and reduces the security of the entire program.