Summary of this pointer

Source: Internet
Author: User
(Collected on the Internet about the essence of this pointer understanding) Reference (http://hi.baidu.com/271032830/blog/item/a7d065335a821047ad4b5ff0.html) (http://blog.csdn.net/starlee/archive/2008/01/24/2062586.aspx) first to understand the meaning of class. Class should be understood as a type, like int and char, which is a user-defined type. (Although it is much more complicated than the build-in type like int char, you must first understand that they are of the same type ). This type can be used to declare a variable, such as int X and myclass my. In this way, just as variable X has the int type, variable my has the myclass type.
If you understand this, you just need to explain this. In my, this is the pointer to my. If there is another variable myclass Mz, This of MZ is the pointer to MZ. In this way, it is easy to understand that the type of this should be myclass *, and the unreferenced * this should be a variable of the myclass type.
Generally, you need to use the type variable itself when defining the class, because you do not know the variable name at this time (for general purpose, it is impossible to fix the actual variable name ), use a pointer like this to use the variable itself.
1. The usage of this pointer:
The this pointer of an object is not part of the object and does not affect the result of the sizeof (object. This scope is within the class. When a non-static member of the struct class in the non-static member function of the class, the compiler automatically transmits the address of the object to the function as an implicit parameter. That is to say, even if you do not write the this pointer, the compiler also adds this during compilation. It serves as an implicit parameter of non-static member functions and accesses to all Members are carried out through this.
For example, if you call date. setmonth (9) <==> setmonth (& date, 9), this helps complete this conversion.
2. Use of this pointer:
One case is that when the class object itself is returned in the non-static member function of the class, return * This is directly used; the other case is that when the parameter and the member variable name are the same, for example, this-> N = n (n = n cannot be written ).
3. Example of this pointer program:
This pointer exists in a member function of the class and points to the address of the class instance where the called function is located.
Use the following program to describe the this pointer
# Include <iostream. h>
Class Point
{
Int X, Y;
Public:
Point (int A, int B) {x = A; y = B ;}
Void movepoint (int A, int B) {x + = A; y + = B ;}
Void print () {cout <"x =" <x <"Y =" <Y <Endl ;}
};
Void main ()
{
Point point1 (10, 10 );
Point1.movepoint (2, 2 );
Point1.print ();
}
When the object point1 calls the movepoint (2, 2) function, the address of the point1 object is passed to the this pointer.
The movepoint function is prototype void movepoint (point * This, int A, int B). The first parameter is a pointer to this class object, we didn't see this when defining a member function because this parameter is implicit in the class. In this way, the point1 address is passed to this, so the movepoint function is explicitly written:
Void movepoint (int A, int B) {This-> X + = A; this-> Y + = B ;}
That is, after point1 calls this function, the data member of point1 is called and updated.
That is, this function process can be written as point1.x + = A; point1. y + = B;
4. A typical answer to this pointer:
When you enter a house,
You can see tables, chairs, floors, etc,
But you cannot see the whole picture of the house.

For an instance of a class,
You can see its member functions and member variables,
But what about the instance itself?
This is a pointer that always points to your instance.

Certificate --------------------------------------------------------------------------------------------------------------------------------------------------------------------

It is actually a default predefined pointer in the class definition. When a member function is called, the system ensures that this pointer always points to the object that generates the call and automatically passes the pointer to the function as a variable. At the same time, this pointer exists only between objects and member functions.

[Example] the following program creates a class called power to calculate the power of a number:

Power
{
PRIVATE:
Double B, Val;
Int E;
Public:
Power (double base, int exp );
Double get_power () {return val ;}
};
Power: Power (double base, int exp)
{
B = base;
E = exp;
Val = 1;
If (exp = 0)
Return;
For (; exp> 0; exp --)
Val = Val * B ;}
Void main ()
{
Power X (4.0, 2), y (2.5, 1), Z (5.7, 0 );
Cout <X. get_power () <"";
Cout <Y. get_power () <"";
Cout <Z. get_power () <"/N ";
}

In a member function of a class (such as power (), you can directly reference a data member of a class without the use of any object or restriction descriptions of the class. Therefore, the statement B = base in the power () constructor of the power class means that the value of the base parameter will be assigned to the data member B in the object that generates the call. The program defines three power objects X, Y, and Z respectively. The Compiler associates the object's member functions with the data members of the same object during the call, therefore, the compiler actually passes a hidden pointer to the object to be referenced by a function call, that is, the this pointer. The same statement can be rewritten as follows:

This-> B = base;

This indicates that when a function call occurs (for example, when a power Class Object X is created), the compiler sends the constructor power () A this pointer pointing to object X, and implicitly use this pointer to access the copy of B belonging to object X. In fact, the statements such as B = base in the above power () function are simply abbreviated. The following is a complete power () function rewritten using the this pointer:

Power: Power (double base, int exp)
{
This-> B = base;
This-> E = exp;
This-> val = 1;
If (exp = 0) return;
For (; exp> 0; exp --)
This-> val = This-> Val * This-> B;
}

In this example, the data member name prefix expression this-> is valid but has no effect, because the use of this pointer is inherently implicit. A friend function is not a member of a class and does not have the this pointer. A static member function does not have the this pointer. However, in some other cases, the this pointer must be used to specify the currently called object. For example, when the operator is overloaded, it is very important to see the this pointer, it is often necessary in some types of linked list management.
Bytes ----------------------------------------------------------------------------------------------------------
This is constructed before the start of the member function and cleared after the end of the member function.
This life cycle is the same as the parameters of any function, and there is no difference.
Because, by default, the first parameter of a member function is this.
Example:
Class {
Public:
Int func (INT p ){}
};
In the compiler's opinion, the func prototype should be
Int func (A * const this, int P );

It is constructed before the member function is executed.
The member function is executed and cleared.

If there is no member function in the class or struct, this is not a constructor. It can only be used as a struct of C.
Read C ++ primer and find the "this pointer" section.
Callback <further understanding> has the following simple class: Class cnullpointcall
{
Public:
Static void test1 ();
Void Test2 ();
Void test3 (INT itest );
Void test4 (); Private:
Static int m_istatic;
Int m_itest;
}; Int cnullpointcall: m_istatic = 0; void cnullpointcall: test1 ()
{
Cout <m_istatic <Endl;
} Void cnullpointcall: Test2 ()
{
Cout <"very cool! "<Endl;
} Void cnullpointcall: test3 (INT itest)
{
Cout <itest <Endl;
} Void cnullpointcall: test4 ()
{
Cout <m_itest <Endl;
}
Are the following codes correct? What will be output? Cnullpointcall * pnull = NULL; // yes, it is to assign a null value to the pointer.
Pnull-> test1 (); // call 1
Pnull-> Test2 (); // call 2
Pnull-> test3 (13); // call 3
Pnull-> test4 (); // call 4
You must be wondering why I asked this question. How can a null pointer be used to call a class member function ?! However, this is surprising: Except for the call 4 line of code, the call of the other three class member functions is successful and the results can be correctly output, the program that contains the three lines of code can run very well.
After careful comparison, we can find the essential difference between the call 4 line code and the other three lines of code: This pointer is used in the member functions of the cnullpointcall class.
For a class member function, not an object corresponds to a separate member function body, but all such objects share this member function body. After the program is compiled, the member function address is determined. This pointer is used to differentiate the data of various objects of this type. All accesses to class data members in the function body will be converted to this-> data member mode.
The this pointer of an object is not part of the object and does not affect the result of sizeof ("object. This scope is within the class. When a non-static member of the struct class in the non-static member function of the class, the compiler automatically transmits the address of the object to the function as an implicit parameter. That is to say, even if you do not write the this pointer, the compiler also adds this during compilation. It serves as an implicit parameter of non-static member functions and accesses to all Members are carried out through this.
For the above example, the value of this is the value of pnull. That is to say, the value of this is null. While test1 () is a static function, the compiler will not pass this pointer to it, so the line of call 1 code can be called correctly (this is equivalent to cnullpointcall: test1 (); For Test2 () and test3 (). Although the compiler will pass the this pointer to these two functions, they do not use the this pointer to invoke member variables of the class, therefore, the call 2 and call 3 lines of code can be called correctly. For the member function test4 (), you need to use the this pointer for the member variable of the callback class, in this case, if the value of this pointer is null, the program will crash.
In fact, we can imagine that the compiler converts test4 () into the following form: void cnullpointcall: test4 (cnullpointcall * This)
{
Cout <this-> m_itest <Endl;
}
The line of call 4 code is converted into the following form: cnullpointcall: test4 (pnull );
Therefore, the program crashes when m_itest is accessed through this pointer.
Next, let's look at the compilation Code Compiled with VC 2005 to explain in detail the magic this pointer.
The compilation code generated by C ++ code above is in the following form: cnullpointcall * pnull = NULL;
0041171e mov dword ptr [pnull], 0
Pnull-> test1 ();
00411725 call cnullpointcall: test1 (411069 H)
Pnull-> Test2 ();
0041172a mov ECx, dword ptr [pnull]
0041172d call cnullpointcall: Test2 (4111e0h)
Pnull-> test3 (13 );
00411732 push 0dh
00411734 mov ECx, dword ptr [pnull]
00411737 call cnullpointcall: test3 (41105ah)
Pnull-> test4 ();
0041173c mov ECx, dword ptr [pnull]
0041173f call cnullpointcall: test4 (411032 H)
By comparing the assembly code generated by the static function test1 () and the other three non-static function calls, we can see that: before a non-static function is called, the pointer pnull (that is, this pointer) pointing to the object is put into the ECX register (mov ECx, dword ptr [pnull]). This is the special feature of the this pointer. You can see the difference between the this pointer and the common function parameters in the C ++ code assembly code of call 3: The common function parameters are directly pushed to the stack (push 0dh ), this pointer is put into the ECX register. If you want to use a class member variable in a non-member function of the class, you can access the ECX register to obtain the this pointer to the object, then, the corresponding member variables are found by adding the offset of the member variables to this pointer.
The following example illustrates how the this pointer is passed to the member function and how to use this to access member variables.
Still a very simple class: Class ctest
{
Public:
Void setvalue (); Private:
Int m_ivalue1;
Int m_ivalue2;
}; Void ctest: setvalue ()
{
M_ivalue1 = 13;
M_ivalue2 = 13;
}
Use the following code to call the member function: ctest test;
Test. setvalue (); the Assembly Code of the above C ++ code is: ctest test;
Test. setvalue ();
004117dc Lea ECx, [test]
004117df call ctest: setvalue (4111cch)
Similarly, put the pointer to the object in the ECX register, and then call the member function setvalue () of the ctest class (). The address 4111cch is actually a jump command, which is transferred to the member function setvalue. 004111cc JMP ctest: setvalue (411750 H)
The 411750h is the address of setvalue (), a member function of the ctest class. Void ctest: setvalue ()
{
00411750 push EBP
00411751 mov EBP, ESP
00411753 sub ESP, 0cch
00411759 push EBX
0041175a push ESI
0041175b push EDI
0041175c push ECx // 1
0041175d Lea EDI, [ebp-0CCh]
00411763 mov ECx, 33 H
00411768 mov eax, 0 cccccccch
0041176d rep STOs dword ptr es: [EDI]
0041176f pop ECx // 2
00411770 mov dword ptr [ebp-8], ECx // 3
M_ivalue1 = 13;
00411773 mov eax, dword ptr [this] // 4
00411776 mov dword ptr [eax], 0dh // 5
M_ivalue2 = 13;
0041177c mov eax, dword ptr [this] // 6
0041177f mov dword ptr [eax + 4], 0dh // 7
}
00411786 pop EDI
00411787 pop ESI
00411788 pop EBX
00411789 mov ESP, EBP
0041178b pop EBP
0041178c RET
The following is an analysis of the key lines in the above assembly code:
1. Press the value in the ECX register to the stack, that is, press this pointer to the stack.
2. The ECX register outputs the stack, that is, the this pointer outputs the stack.
3. Put the value of ECx in the specified place, that is, the this pointer in [ebp-8.
4. Put the value of this pointer into the eax register. At this point, the this pointer points to the test object. The test object only has two int-type member variables and is stored continuously in the test object memory. That is to say, the this pointer currently points to m_ivalue1.
5. assign a value of 0dh (hexadecimal 13) to the address pointed to by the register eax ). In fact, it is to assign 13 values to the member variable m_ivalue1.
6. Same as 4.
7. Add a value of 4 to the address pointed to by the register eax. As described in section 4, the memory of the eax register is placed with the this pointer, And the this pointer points to the member variable m_ivalue1 of the continuously stored int type. This pointer is added with 4 (sizeof (INT), that is, the address of the member variable m_ivalue2. Therefore, this row assigns values to the member variable m_ivalue2.
Through the above analysis, we can understand the implementation method of this pointer in C ++ from the bottom layer. Although different compilers use different processing methods, the C ++ compiler must comply with the c ++ standard, so the implementation of this pointer should be similar.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.