Some beginners seem to have some confused to call the function of the pointer, I am presenting two sentences. I hope some help for beginners, and I also ask the expert to finger. Learn each other and make progress together. First, please see the small program below: * / # include
Take a look at A: A: char * mystrcpy (char * p) {char * str = new char [15]; // This has been modified. STRCPY (STR, "I LVOE C !"); P = Str; Return Str;} STR output can be obtained correctly, and P output is still not. Because Str is the memory allocated in the heap, the memory allocated in the heap is always occupied, until the end of the main function. So it will be released in time when it is no longer used. Here, the function returns the memory address in the heap, so when the COUT << MyStrcpy (P) << ENDL statement is, the output is a string stored in the heap. You can get the correct answer. However, there is a heap memory release problem, and should remember to release it in the function of calling the function. But when the myscpy function and the main function is not written by the same person, the memory leaks will eventually cause the system. Maybe you will say: Cut, isn't it 15 bytes, what is going on, now there is a very low memory. To know that the function may be transferred multiple times, such as for (int i = 0; i <100000000; i ) {for (int J = 0; j <100000000; J ) {char * p = null; char * str = MySTRCPY (P); // do something ...}} and the program may be a few years,.. So it is best to avoid writing such a function, it is best to assign a stack in a function, and then release the stack memory before the end of the function. If you really need to allocate a stack memory in a function, you should do some protection work. For example: Class Object; // This is a large class defined elsewhere. Std :: auto_ptr
When a function is called, the memory is allocated in the stack space, first assign some memory to store the address returned to the main modifier, then allocate the memory, then put the arguments COPY, this Execution of code that is called a function is encountered when encountered a return result; statement, a temporary object will be generated at the modified value of the function, and then the result of the result is passed (so please note that the return is not the result itself, but A copy of the Result, or the address of the object), then collects the stack space memory, and finally continues to run in the main adjustment function. Let's look at an example: I want to write a function whose function is to exchange two integers, and then return them and. INT myswap (int val1, int avl2) {int result = VAL1; VAL1 = VAL2; VAL2 = VAL1; RESULT = VAL1 VAL2; RETURN Result;} int main () {Int a = 3; int b = 5; int sun = Myswap (a, b); cout << "a =" << a << "/ tb =" << b << "/ ta b =" << Sun << Endl; Return 0;} When the myswap function is mobilized, first allocate memory in the stack, store the address returns to the address. The memory space of the variable VAL1 and VAL2 is then assigned, and the values of A and B are then copy to VAL1 and VAL2, respectively. Then, the memory space of TEMP is started and initialized (so four memory is allocated in the stack space belonging to the called function, and each of the specific data types and platforms, these should be all in the Win32 platform. It is 4 bytes.). Then swap the value of VAL1 and VAL2, and then seek, when it encounters return result;, a temporary object TEMP is generated at the return of the function, and then the value of the result is copy to TEMP. After the COPY is completed, the stack area is retracted, and then executes Sun = Temp; After the statement ends, the life of TEMP is over. We see that the values of Val1 and VAL2 are exchanged throughout the process, and the values of A and B have not exchanged. Or the original value. This is the situation of the value, and the entire process has several times. If the two objects participating in the exchange are not integrated, the COPY constructor and the destructive function must be mobilized multiple times, and there are many overhead. Therefore, the pass value is a low efficiency.
Do the following modification: int * myswap (int * VAL1, INT * AVL2) {int result = * VAL1; * VAL1 = * VAL2; * VAL2 = * VAL1; Result = * VAL1 * VAL2; RETURN & RESULT;} int Main ) {INT A = 3; INT b = 5; int * sun = myswap (& A, & b); cout << "a =" << a << "/ tb =" << b << "/ ta b = "<< * Sun << endl; return 0;} When the function is mobilized, the memory, pointer variable VAL1, VAL2, which is used to save the returned address is sequentially allocated. Then, respectively, the address COPY of A, B is then assigned a space of the result, followed by the extracting the address in the VAL1 memory space, and then assigns the number of the address (ie: A) to the Result, then exchange A, B value, then, finally, finally put the result's address COPY to TEMP (at this time Temp is a pointer), then collect the stack space, then assign the TEMP content to Sun, Sun points to the stack that has been recovered. One memory, cout << * sun << Endl; belongs to illegal access. So the program should be changed: int result; // global variable. Assign memory space in the global data area. INT * myswap (int * VAL1, INT * AVL2) {result = * VAL1; * VAL1 = * VAL2; * VAL2 = * VAL1; Result = * VAL1 * VAL2; RETURN & RESULT;} This encountered Return & Result , Put the address of the memory of the overall variable RESULT in the global data area to TEMP, then collect the stack space, (cannot recover the result space, because it is not in the allocated memory), then assigning the contents of TEMP to Sun, Such Sun's content is a period of memory in the global data area. Everything is OK. This is an addressing method.
Finally, look at the delivery reference, change the program to: int & mal1, int & avl2 {int result = VAL1; VAL1 = VAL2; VAL2 = VAL1; Result = VAL1 VAL2; RETURN RESULT;} int main () {INT A = 3; int b = 5; int & sun = myswap (a, b); cout << "a =" << a << "/ tb =" << B << "/ ta b =" << Sun << Endl; Return 0;} When the function is called, the stack space is allocated: return the address, reference VAL1, and the memory space of the reference VAL2, the size and pointer is the same. Then, the address COPY of A, B is then assigned a subsultative space, and the content is taken out when VAL1 is used (which is the address of A.) Remove the number of A, which gives it to Result, which is almost the same below. . There is also a problem that references to returning local variables. Change to: int result; // Global Variable INT & MYSWAP (INT & VAL1, INT & AVL2) {Result = VAL1; VAL1 = VAL2; VAL2 = VAL1; Result = VAL1 VAL2; RETURN RESULT;} When encountering returnrate; Give the address of the global variable RESULT to TEMP, collect the stack space, give the TEMP to Sun, the Sun's content is the address of the global variable Resul, only the compiler knows that he is a reference, after all of its operations Is the number of ports stored in the address saved in its memory. We have seen that the reference transfer is achieved by a pointer, but his operation is the same as the pass value. The killing power of the pointer is too strong. If you just reference the object, please do not use the pointer with reference. Here is another trick about the value.
When the return value is a custom object, we'd better use the reference to return instead of the value returned, but sometimes our program requires returns an object, and when the return reference is not suitable, the following cases are compared: Class Object; Object Func (Object & a, Object & B) {// do something object Sun (A B);} should be written: Object Func (Object & A, Object & B) {Return Object (A B); What is the difference between the two? The former first creates a Sun object and initializes, then create a TEMP object, then call the COPY constructor to copy the Sun to Temp. The latter directly establishes the TEMP object, and uses (A B) to initialize Temp. That is, the former is equivalent to: Object Sun (A B); Object Temp = Sun;, the latter is equivalent to: TEMP (A B); two steps of constructing Sun and sectors. Corresponding, we should also write int RES (x1 x2); RETURN RES; directly write: return Int (x1 x2); return to our topic, why not do the P output of A situation? Char * mystrcpy (char * p) {char * str = new char [15]; // This has been modified. STRCPY (STR, "I LVOE C !"); P = Str; Return Str;} Function Char * MyStrCPY (CHAR * P) When the stack space is allocated: return the address, the space of the Conversion P, then put the real The content of the reference (ie: null, note, the content of P is transmitted, not the address of the P itself), then assigns the space of the STR pointer, then assigns a 15-byte space in the heap, STR points to the stack space The first address, then call the STRCPY function, so that the contents in the heap are "I Love C !", And then the STR is assigned to P, at this time, the meticulum P points to the heap space. Then return to the STR, then collect the stack space, STR and the shape of P, are not. Everyone saw that in addition to giving the value null copy of the real parameters Null Copy, there is no relationship again. The P or NULL in MAIN after the function call. To think that the parameters of the actors can change the parameters of the function to the pointer to the pointer: char * mystrcpy (char ** p) // This has been modified, please modify the function of the function accordingly. {Char * str = new char [15]; // This has been modified.
STRCPY (STR, "I LVOE C !"); * p = Str; // has been modified here. Return Str;} and change the call in the MYSTRCPY in the main function to: MySTRCPY (& P), so that the PO output can be obtained correctly. Next, look at B: b: char * mystrcpy (char * p) {static char STR [15]; // This has been modified. STRCPY (STR, "I LVOE C !"); P = Str; Return Str;} B, STR output can be obtained correctly. P Output is not available (why the same A situation). We know that when a program is executed, the memory space is divided into four districts: Code Area: Store my program code. Global data: global variables, static data, constants allocate memory in this area. Stack Area: The local variable, function parameters, return data, return address, and the like allocated to the run function are stored in the stack area. Heap Area: The area allocated by New, New [], Malloc and other functions. Among them, in particular, the memory needs to be particularly concerned. If the assigned memory is not used to call DELETE, DELETE [], free and other functions to be released, and should pay attention to match, the memory allocated by the new, you should call Delete. Release, you cannot call DELETE [] to be released. And you can only release it once. For delete p; if P is a pointer to the custom type, the false code it implemented is as follows: if (p == null) {return;} // Call the destructor of the object points to the object to the object; P-> Destruction (); free (p); we see, for a value of NULL P, regardless of how the delete P is not a problem, but for a pointer P, a pointer P, continuous call two delete p error. Because when the first call, the destructor is first called, then release the heap memory. Just simply release, but did not clear the content in the memory, just saying that when other programs need to be a pile of memory, you can use this released memory, and do not change the contents of P to zero, The address in P does not change, or points to the pile. Some beginners think delete p; that is, the P 's life is over. Not like this. For the following code: Class Object; Object * g_pObject = new object; void func () {// with g_pobject do something ... delete g_pobject;} first assign 4 bytes of space to variable g_pobject, Then, in the stack area, the SIZEOF (Object) size memory is then invoked, then the constructor of the Object is called, and an Object object is constructed, and then the first address COPY of the heap space is stored in the memory space of the global variable g_pobject. When the FUNC function is called, delete g_pobject; means that the content stored in the four byte memory space allocated by G_PObject, look at the one where it point to the pile, then put the one The acres is three minutes. The entire process g_pobject is still the original g_pobject; it is still in the 4-byte memory space allocated in the global data area, and there is no delete, and there is still no change even in his value.
His life is still lush, and always survive to the main function in the same time. So at this time, as long as we determine that the original allocated stack has been released, we can use G_PObject to let him point to other places. How do we determine that the inside of his original pointing is released, is it doing this? Void func2 () {if (g_pobject! = null) {delete g_pobject;} g_pobject = new object;} This is not good, if the FUNC function has been called before this, put the heap memory release, but g_pobject does not Set zero, then delete g_pobject; will be called again, an error. Of course, we can change the program to this: void func () {if (p! = Null) {// with g_pobject do something ... delete g_pobject; g_pobject = null;}} void func2 () {=} void func2 () {= ! = Null) {delete g_pobject; g_pobject = null:} g_pobject = new object;} Good idea, delete then is a good program habit. There is no relationship with a pointer delete that is zero. Since we often want to write a assignment statement after Delete, there is a more simple way, can only write a statement? We rewrite the operator delete () function: void Operator delete (void * p) {delete p; p = null:} void func () {if (p! = Null) {// with g_pobject do something ... delete g_pobject }} Void func2 () {delete g_pobject; g_pobject = new object;} This is not lineless, because p = null: just sets the shape P to zero, and there is no half relationship between G_PObject. Maybe you will immediately say that the pointer is coming over! Oh, I also want to, just C regulations, the Operator delete function return type can only be void, the first parameter can only be Void *, there is a second number Can only be SIZE_T. I have to think about him. Define a template function: Template
Just open a precedent, I have never seen a function name with numbers, I don't know if you have seen it? So our template function can be written: Template