The following C ++ Code defines a class point:
Class point <br/>{< br/> Public: <br/> point (float xval); <br/> virtual ~ Point (); </P> <p> float X () const; <br/> static int pointcount (); </P> <p> protected: <br/> virtual ostream & print (ostream &) const; </P> <p> float _ x; <br/> static int _ point_count; <br/> };
Now, the PT: Point PT object of the point object is defined. The question discussed in this note is: If you want to design the memory layout of this object, how would you design it? (The memory layout here refers to the memory emissions of each member of the object)
The following describes three memory la s proposed by Lippman in Deep Exploration C ++ object model.
1. Simple Method (original article: Simple Object Model)
Point pt; as shown in:
Looking at the figure above, the question is: "Where is simplicity ?", Simple in the eyes of compiler designers... From the compiler designer's point of view, this design is relatively simple and is in line with their lazy habits, because when every object comes out and there are several members, just assign several pointers, for example, PT has 7 members (Next we will discuss inheritance), so there are 7 pointers. If it is a data member, it points to the actual data; if it is a member function, it points to the entry address of the function. In addition, this approach also has a second advantage, that is, avoiding the fact that members of different sizes have different buckets. What does it mean? For example, a class has two data members: Char and Int. Char occupies one byte, while int occupies four bytes, but I use a 32-bit server, therefore, the default situation is 4-byte alignment (for information about the structure Alignment Method, please google). Therefore, when the compiler allocates space for objects, you have to consider these situations... The current model is very good. Every pointer is 4 bytes, so there is no alignment or alignment statement. The compiler designers are much simpler.
Let's take a look at the example of how this model is used for inheritance and polymorphism (in my discussion, what is written in the book is not very detailed)
For example, the following code:
Class point2d: Public point <br/>{< br/> Public: <br/> point2d (float xval, float yval); <br/> virtual ~ Point2d (); <br/> virtual ostream & print (ostream &); <br/> protected: <br/> float _ y; <br/> }; <br/>
So now we define a point2d object pt2d. How is the memory layout of this object reflected through the so-called simple memory layout above?
There are two methods:
1. In pt2d, assign another pointer to the layout of the base class.
Next, let's take a look at how such a layout achieves polymorphism?
The preceding virtual function print is used as an example, for example, the above Code. My solution is: when calling a virtual function, first look for the part of the derived class, whether there is a pointer to print (in this example, There Is); if there is, it calls the derived class, if not, go to the base class.
Do you feel familiar? For example, in the implementation code of MFC message ing... Refer to the "MFC message ing principle" written below"
2. The second layout of the derived class is to embed the members of the base class directly into the derived class.
The implementation of polymorphism is also achieved through a method similar to the first derivative layout above, that is, first finding the derived class and then finding the base class.
In fact, this layout has a third advantage, that is, to reduce compilation dependencies. For example, one day, you should change the name of a member in the class or change the implementation of a member function, for this layout, you only need to re-compile the actual definition of the class. For the class object and its usage, you do not need to compile (but not when adding or removing members)
The advantages seem to be quite good. But according to China's great Yin and Yang theory, we should say the following Disadvantages:
I don't know what the three advantages are? I don't know whether I have seen it or not. An important thing is missing, that is, efficiency. efficiency is one of the most important indicators of C ++ (the two most important indicators of C ++: compatible with C, catch up with the efficiency of C); therefore, the disadvantage is that there is no efficiency.
For a detailed analysis, each object has a pointer to the member function of this class, which will cause a large number of duplicates. When polymorphism occurs, you have to first find a derived class and find a base class, which will waste a lot of time and space. How can c ++ accept it? Therefore, this memory layout does not appear in the actual C ++ compilation. However, this practice inspired Lippman to invent the pointer to object members.
2. Table-driven memory Layout
Or the above point Class Object pt. What is this model?
Compared with the first layout above, the table-driven memory model also has an indirect layer. The advantage of doing so is that the layout of the PT itself remains unchanged when the Members are extended, the two tables are just defined. The Compiler may optimize the layout based on these conditions to reduce compilation dependencies.
Disadvantages: Needless to say, the simple memory layout above is already inefficient and not received by C ++. What's more, this will be eliminated immediately. However, this model also inspired Lippman: the virtual function table was invented.
What is the model under inheritance? See the following figure:
About table DRIVER:
In the above layout, because the object's memory only has two pointers pointing to two corresponding tables, it is called a table driver. Table drivers are used in many places, for example: finite State Machine (Compiler Principle and IP Protocol) is a widely used method. Its disadvantage is efficiency and its advantage is flexibility. I will not talk about it here. If you are interested, you can refer to the relevant articles.
By the way, in fact, the message ing practice in MFC is not so much a reference to the first layout, it is better to refer to the second layout, table-driven (similar to QT signal and slot, VCL event mechanism, etc)
<! -- [If! Supportlists] --> 3. <! -- [Endif] --> memory layout of real objects in C ++
The question finally came out. Speaking of this, I think of a classic saying: "beauty is like flowers. It only shows the beauty of a green leaf "~
The green leaves have been introduced. Let's see the flowers.
The following describes the features of the memory layout:
1. Non-static (nonstatic) data members. Each object has a copy in its memory space.
2. static data members. Static and non-static member functions have only one entity in the entire memory.
3. Each class that defines virtual functions has a virtual function table; the table item contains the function calls related to this class (you can just draw a line about the inheritance)
4. Each object that defines a virtual function has a pointer (like the _ vptr_point above) pointing to the virtual function table of the class.
Note:
1) If two objects are defined: Point pt1 and point pt2, The pt1 and pt2 _ vptr_point point to the same table. * (Pt1. _ vptr_point) = * (pt2. _ vptr_point), because each class has only one virtual function table!
2) _ vptr_point is simulated only to illustrate the problem. That is to say, the C ++ program cannot access this item. (To show my erdition, write a verse to verify it here: I do not know the true colors of the mountains, only because I am here ), therefore, you cannot understand the underlying mechanism of C ++ through C ++ itself. You can only understand the underlying language (assembly, machine code, or even 0-1 Current)
The disadvantage is the advantages of the above two types. This advantage is the disadvantages of the above two models, which is so simple.
Next we will end this note with a point2d memory layout diagram. (The table pointed to by _ vptr_point2d is the virtual function table of point2d. Check whether the table is different from the above point PT layout)
For more information about the impact of this model on C ++, see the following section ~
PS. All the subjects of this note come from Chapter 1, Section 1, "Deep Exploration of C ++ object model.