Data Layout of c ++ Object Model
Data Semantics
Class X {};
Class Y: publicvirtual X {};
Class Z: publicvirtual X {};
Class A: publicY, public Z {};
Sizeof (X) = 1, sizeof (Y) = 4, sizeof (Z) = 4, sizeof (A) = 8; test results on visualc ++ 6.0 (compiler with special processing for emptyvirtual base class)
Otherwise, the result is ,.
In fact, the size of Y and Z is affected by three factors:
1. additional burden caused by the language itself
2. Compiler Optimization in special cases
3. Alignment restrictions
In special cases, the object layout is as follows:
The object layout is as follows:
Nonstaticdata members is directly stored in each classobject. The same is true for the inherited nonstatic data members, but the order of them is not forcibly defined. As for staticdata members, it is placed in a globaldata segment of the program and will not affect the size of individual classobject.
One Data Member binding
1. Datamembers binding
Extern int x;
Class Point3d
{
Public:
// The analysis of the function itself will be delayed until the braces on the right of the class Declaration appear.
Float X () const {return x ;}
//....
Private:
Float x;
};
The Analysis of memberfunctions itself will not start until the entire class declaration appears. That is, the X returned by the x () function will be the x defined in the class.
2. argumentlist of Membersfunctions
Typedef int length;
Class Point3d
{
// Typedef char length;
Public:
// Length is determined as global
// _ Val is determined as Point3d: _ val
Void mumble (length val) {_ val = val ;}
Length mumble () {return _ val ;}
Private:
// Length must be seen before "the first reference operation of this class on it"
// Such a statement will invalidate the previous reference operation
Typedef char length;
Length _ val;
};
The above language still requires a defensive program style: the "nestedtype Declaration" is always placed at the beginning of the class.
2. Data Member Layout
The order of Nostatic data members in classobject will be the same as the order in which it is lifecycle. staticdata members involved in any stage will not be placed in the object layout.
C ++ standard requires that, in the same accesssection (that is, private, public, protected, and other segments, the arrangement of members only needs to meet the condition that "members that appear later have a higher address in classobject.
C ++ standerd also allows the compiler to arrange data members in multiple accesssections without having to care about the order they appear in the class declaration.
It is worth noting that the amount of accesssection does not incur additional burden. For example, if you declare 8 members in a section or 8 members in a total, the object size is the same.
3. Data Member access
1. Staticdata members
You do not need to use class object to access staticmembers.
To get a pointer to its classmember, because static member is not included in a classobject. For example:
& Point3d: chunkSize;
The following memory address is obtained:
Const int *
2. NonstaticData Members
Nonstatic data members is directly stored in each classobject. Unless otherwise specified
(Explic) or implicit classobject, there is no way to directly access them. In member function, the compiler automatically synthesize the this pointer. To access a nonstaticdata member, the compiler needs to add the start address of classobject to the offset of data member. The offset of each nonstaticdata member can be known during compilation.
Point3d origin, * pt;
Origin. x = 0.0;
Pt-> x = 0.0;
What are the major differences between the two access methods? The answer is "When Point3d is a derivedclass, but there is a virtual base class in its inheritance structure, and the accessed member (such as x in this example) is a member inherited from the virtualbase class, there will be a major difference.
IV inheritance and Data member
1. Only inheritance without polymorphism
In the c ++ inheritance model, what a derivedclass object represents is the sum of its own members and its baseclass members. The order of derivedclass members and baseclass members is not specified forcibly. Generally, the base class is in front of the base class.
The following errors will be made when two irrelevant classes are merged into a pair of "type/subtype": 1. some functions with the same operation may be designed repeatedly; 2. dividing a class into two or more layers may expand the space required to "express the abstraction of the class system. C ++ language guarantee"Baseclass subobject appearing in derived class has its integrity as is".
Class Concrete
{
Private:
Int val;
Char c1;
Char c2;
Char c3;
};
Sizeof (Concrete) = 8
Split Concrete into three layers:
Class Concrete1
{
Public:
//....
Private:
Int val;
Char bit1;
};
Class Concrete2
{
Public:
//....
Private:
Char bit2;
};
Class Concrete3
{
Public:
//....
Private:
Char bit3;
};
We can conclude that sizeof (Concrete3) is 16, which is twice as much as originally designed. The object layout is as follows:
Why base classsubobject remains unchanged in derivJedclass
2. Add Polymorphism
The extra burden of space and access time caused by polymorphism:
① Import a virtualtable to store it in the location of every virtual function it declares.
Address. The number of elements in this table is generally the number of declared virtualfunctions, plus one or two slots.
② Import a vptr in each classobject to provide links during execution so that each
The object can find the corresponding virtualtable.
③ Enhance the constructor so that it can set an initial value for the vptr and point it to the virtual
Table.
④ Enhance the destructor so that it can erase the vptr "pointing to the virtualtable related to the class. Note
The call order of destructor is reversed: From derivedclass to base class.
All compilers do not mean that vptr is placed in the object's header, that is, at the end of the object.
5. pointer to Data Members
/*
Pointer to Data Members
*/
# Include
Usingnamespace std;
ClassPoint3d
{
Virtual ~ Point3d ();
Public:
Static Point3d origin;
Float x, y, z;
};
Intmain ()
{
// FloatPoint3d: * instead of float *
Printf (& Point3d: x = % p, & Point3d: x );
Printf (& Point3d: y = % p, & Point3d: y );
Printf (& Point3d: z = % p, & Point3d: z );
}
# Include
Usingnamespace std;
StructPoint
{
Int x, y;
Double d1, d2;
}
IntAdd (Point arr [], int size, int Point: * p)
{
Int sum = 0;
For (int I = 0; I <size; I ++)
Sum + = arr [I]. * p;
Return sum;
}
DoubleAdd1 (Point arr [], int size, double Point: * p)
{
Int sum = 0;
For (int I = 0; I <size; I ++)
Sum + = arr [I]. * p;
Return sum;
};
Intmain ()
{
Point pp [3] = {1, 2, 1.0, 2.0}, {3, 4, 1.0, 2.0}, {5, 6, 1.0, 2.0 }};
Cout <
Cout <
}