Deep Exploration of the C + + object model (Inside the C + +) Learning Notes

Source: Internet
Author: User
Tags bitwise shallow copy

Reprint: http://dsqiu.iteye.com/blog/1669614

Chapter One about objects

Layout costs after using the class package:

Class does not add cost, the data members are directly contained within each class object, just like C struct. member functions, though included in the class declaration, does not appear in object. Each non-inline function produces only one functional entity. As for the inline function, a function entity (the body of the function is expanded at the point of invocation) is generated where each call is used.

The main additional burden on the layout and access time of class is generated by virtual, including:

The virtual function mechanism is used to support an efficient execution-time binding (runtime bindings).

Virtual base class is used to implement "multiple occurrences of the base class in the inheritance system, with a single shared entity".

There are, of course, some additional burdens to chop into succession, which occurs between "a derived class and its second or subsequent base class conversion".

C + + object model

In the C + + object model, the nonstatic data members are placed within each class object, and the static data members are stored outside of the class object. The static and NONSTAITC function are also placed outside of all class object. Virtual functions is supported in two steps:

1. Each class produces a bunch of pointers to virtual functions, placed in a table, called Virtual table (VTBL).

2. Each class object is added with a pointer to the associated virtual table. Usually this pointer is called VPTR, and Vptr's settings and resets are automatically performed by each class's constructor, destructor, and copy assignment operators.

C + + supports polymorphism in the following ways:

1. Through a set of implicit conversion actions. For example, convert a derived class pointer to a pointer to its public base type.

2. Through the virtual function mechanism.

3. Via the dynamic_cast and typied operators.

How much memory is required for class object:

1. The total size of its nonstatic data members.

2. Add any hesitation alignment demand and padding (fill) up the space.

3. Add any additional burden generated by the interior in order to support virtual.

Pointer type: Tells the compiler how to interpret the memory content in a particular address and its size (for example: A string is a traditional 8 bytes (including a 4byte character pointer and an integer representing the length of the string). Transformation (CAST) is actually a compilation instruction, most of which does not change the real address contained in a pointer, it only affects the "size of the indicated value memory and its content" interpretation.

Chapter II Semantic Study of constructors

2.1 Default Constructor

When required by the compiler, the default constructor is synthesized to perform only the tasks required by the compiler (the members are properly initialized).

Member Class Object with Default Constructor

The compiler comes out: If a Class A contains one or more member class objects, then each constructor of class A must invoke the default classes of each member constructor 。 The compiler expands the existing constructors, placing some code in it so that user code is called (in the order of calls member objects in the class declaration order) necessary to default constructors before it is executed.

Base class with Default Constructor

The compiler invokes the default constructor of all base class constructor before the Member class Object's default constructor is inserted and called (the order of calls is based on their declaration order).

Class with a Virtual Function

The following two scenarios also require the synthesis of default constructor:

1.class declares (or inherits) a virtual function.

The 2.class derives from an inherited chain, one or more of the virtual base class.

The extension (constructor) operation occurs during compilation:

1. A virtual function table is generated by the compiler, with the address of the virtual functions of class.

2. In each class object, an additional pointer member (VPTR) is synthesized by the compiler, containing the address of the associated class VTBL.

Class with a Virtual Base class

The implementation of the virtual base class differs greatly from one compiler to another, but the common denominator of each implementation is that the virtual base class must be positioned in each of its derived class object to be ready for execution. For each constructor compiler defined by class, the code "Allow execution time access for each virtual base class" is inserted.

Summarize

In these four cases, the compiler must synthesize a default constructor for the class that does not declare constructor, which is only required by the compiler (not the program). It is able to accomplish its task by "invoking the default constructor of member object or base class" or "initializing its virtual function mechanism or virtual base class for each object" Mechanism "is complete. As for the class that does not exist in these four cases without life constructor is actually not synthesized.

In the synthesized default constructor, only the base class Subobjects (sub-object) and member class objects are initialized. All other nonstatic data member, such as integers, integer pointers, integer arrays, etc., are not initialized, and these initialization operations are necessary for the program, but not for the compiler.

C + + Beginners generally have two misconceptions:

1. If the default constructor is not defined for any class, it will be synthesized.

2. The default constructor compiled by the compiler will explicitly set the defaults for each data member in the class.

2.2 Copy Constructor

There are three cases in which the contents of an object are used as the initial value of another class object.

1. The most obvious of course is the explicit initialization of an object.

2. When object is passed as a parameter to a function

3. When the function returns a class object.

In these three cases, copy constructor is required.

Default memberwise Initialization

If class does not provide a explicit copy constructor, when class object takes "the same other object as the initial value, its interior is in the so-called default memberwise Initialization the way it was done. That is, the value of each built-in or derived data member (such as an array or pointer) is copied from one object to another object, but not its specific contents. For example, copy only the pointer address, do not copy a new pointer to the object, which is a shallow copy, but it does not copy the Member class object, but recursively implement the memberwise initialization.

How is this recursive memberwise initialization implemented?

The answer is bitwise copy semantics and default copy constructor. If class exhibits bitwise copy semantics, the bitwise copy (bitwise copy semantics compiler generated pseudo-code is memcpy function) or the compiler generates default copy Constructor

What is the case that class does not show bitwise Copy semantics? There are four types of cases:

1. When class contains a member class object, and the member class has a default copy constructor [either the Class designer explicitly declares it or is synthesized by the compiler]

2. When class inherits from a base class, and the base class has a copy constructor [either the Class designer explicitly declares it or is synthesized by the compiler]

3. When a class declares one or more virtual functions

4. When class derives from an inherited chain, one or more of the virtual base class

Let's understand why you can't use bitwise copy in these four situations, and what the compiler generated copy constructor has done.

In the first 2 cases, the compiler must place the member or base class "copy constructor call operation" into the synthesized copy constructor.

Reset the pointer to virtual Table

In the 3rd case, because the class contains virtual function, the compiler needs to do the expansion operation:

1. Add the virtual function table, which contains an address of a functioning virtual function;

2. Create a pointer to the virtual function table, placed inside the class object.

Therefore, the compiler must be correctly assigned the vptr of each newly generated class object, otherwise it will run to perform the function of other objects, and the consequences are very serious. Therefore, when the compiler imports a vptr into class, the class is not displayed bitwise semantics, the copy constructor must be synthesized and vptr properly initialized.

Working with Virtual Base Class subobject

The existence of virtual base class requires special handling. A class object with another virtual base class Subobject will also invalidate the "bitwise copy Semantics".

Each compiler's support commitment to virtual inheritance means that the "virtual base class Subobject location in derived class object" must be prepared at the execution time, maintaining "the integrity of the location" is the responsibility of the compiler. Bitwise copy semantics may break this location, so the compiler must synthesize the copy constructor itself.

This means that the copy constructor, like the default constructor, is built when needed, rather than the programmer helping to build without writing the compiler.

2.4 Initialization List

There are four situations in which you must initialize a class's members with an initialization list:

1. When initializing a reference member;

2. When initializing a const member;

3. When a base class constructor is called, and it has a set of parameters (which are actually custom constructors);

4. When a member class constructor is called, and it has a set of parameters.

However, the order of initialization is determined by the class Members declaration order, not by the initialization list.

Chapter III Data semantics

Layout of the 3.2 Data Member

The nonstatic data members are arranged in class object in the same order as they are declared. But C + + standard allows the compiler to freely arrange data members in multiple access sections without caring about the order in which they appear in class.

Access to the 3.3 Data Member

Each member access License (private public protected), as well as its association with class, does not incur any additional burden on space or execution time-either in the individual class objects or in the static data Member itself.

The static data members are considered global variables, and only one entity is stored in the program's data segment, and each time a static member is taken, it is internally converted into a direct reference operation on that unique extern entity. If you take the address of a static data member, you get a pointer to the datatype, not just the pointer to class member.

nonstatic data members want to access a nonstatic data member, the compiler needs to use the start address of class object plus the offset of the data member (it can be learned at compile time).

3.4 Inheritance and Data Member

As long as inheritance does not polymorphic

This situation does not increase the extra burden on space or storage time. In this case, the base class and derived class objects all start from the same address, the difference is only the derived object is larger, to accommodate the self-built nonstatic data members, a derived Class object assigns a pointer or reference to base class, does not require the compiler to mediate or modify the address, it is very moist can occur, and provides the best execution efficiency.

Plus polymorphic

This situation creates additional burdens on space and access time:

1. Import A and virtual table to store the address of each virtual functions it declares.

2. Import a vptr in each class object, providing a link to the execution period so that each object can find the corresponding virtual table.

3. Strengthen the constructor so that it can set the initial value for the vptr to point to the virtual table corresponding to class.

4. Strengthen the destructor so that it can erase the vptr that "points to class-related virtual table".

Multiple inheritance

For a multiple-derived object, assign its address to the "leftmost (first) base class pointer", as in the case of single inheritance, since both point to the same starting address, and the address of the second or subsequent base class specifies the operation, you need to modify the address: plus (or subtract The size of base class Subobject (s) in the middle, if it is downcast.

If you want to access a data member in the second (or later) base class, there is no additional cost because the position of the members is fixed at compile time, so access member is just a simple offset operation.

Virtual inheritance

Class if it contains one or more virtual base class subobjects will be divided into two parts: one invariant local and one shared local. Unchanged local data, always can have fixed offset, this part can be directly accessed, as for the shared part, the performance is virtual base class Subobject, this part of the data, its location because of each derivation operation has changed, so only indirectly access.

If there is no virtual functions, they are exactly the same as C struct.

Fourth Chapter Function semantics

4.1 Member's various invocation methods

nonstatic Member Functions

In fact, the compiler is the member function is internalized into the form of nonmember, through the following conversion steps:

1. Add additional parameter--this to the function.

2. Change the access operation for each NONSTAITC data member to the this pointer.

3. Rewrite the member function as an external one. The selection of function names mangling processing, making it a unique vocabulary.

Virtual Member Functions

Will

Ptr->f (); F () is virtual member function

Internally translated into

(*ptr->vptr[1] (PTR);

which

Vptr represents the compiler-generated pointer to virtual table. It is placed in each class object that declares (or inherits from) one or more virtual functions.

1 is the index value of the virtual table slot, which is associated to the normalize () function.

A second PTR represents the this pointer.

Static Member Functions

cannot be declared as const volatile or virtual.

A static member function is presented outside the class declaration and given an appropriate name through mangling. If you take the address of a static member function, you get its location in memory, which is the address, not a pointer to "class member function", as follows:

&point::count ();

A value is given, and the type is:

unsigned int (*) ();

Instead of:

unsigned int (point::*) ();

4.2 Virtual Member Funcitons

In C + +, a polymorphic representation of "a public base class pointer (or reference) that addresses a derived class object".

Each class will have only one virtual table, and each table contains the corresponding entity address of the active virtual functions function in the class object. These active virtual function includes:

1. The function entity defined by this class (overwrite (overriding) a possible base class virtual function entity.

2. Function entity inherited from base class (not rewritten by derived class)

3. A pure_virtual_called ().

There are three possibilities for a class-inheriting function, virtual table:

1. Inherit the function entity of virtual functions declared by base class. correctly, the address of the function entity is copied to the slot corresponding to the derived class virtual table.

2. Use your own function entity. This means that its own function entity address must be placed in the corresponding slot.

3. You can add a new virtual function. At this point, the size of virtual table will increase by one slot into the function entity address.

Compile time to set virtual function invocation:

Generally speaking, I do not know the true type of the object that PTR refers to. However, you can access the virtual table of the object via PTR.

Although I do not know which Z () function entity is called, but know that each z () function address is placed at the index of slot 4.

So we can put

Ptr->z ();

Converted to: (*ptr->vptr[4]) (PTR);

The only thing that can be known at execution time is: which Z () function entity the SLOT4 refers to.

Virtual Functions under multiple inheritance

Virtual functions is supported in multiple inheritance, and its complexity revolves around the second and subsequent base class, and the "this pointer must be adjusted at execution time". The general rule is to invoke the derived class virtual function by pointing to the second or subsequent base class pointer. The "Necessary this pointer adjustment" operation associated with the call operation must be completed during the execution period.

Virtual Functions under fictitious inheritance

4.3 Performance of the function

The Nonmemeber, static member, or nonstatic member functions are all converted to the exact same form, so the efficiency of the three is exactly the same.

4.4 Pointer to member function

Take a nonstatic data member address, the result is the member in the class layout of the bytes location, so it needs to be bound to the address of a class object, to be able to be accessed.

Take the address of a nonstatic member function, if the function is nonvirtual, then get the real address of the memory, then this value is not complete, also need to bind to the address of a class object, to be able to call the function.

Pointers to "virtual Member Function" supported

For a virtual function, its address is unknown at compile time, and only what is known is the index value of virtual function in its associated virtual table, i.e., for a virtual member function Take its address, all you can get is an index value.

4.5 Inline Funcitons

Parameters passed in the parameter, directly replace the incoming constant, even replace all save, directly into a constant into the function run results, you need to import temporary variables

Local variable local variables will be mangling, so that the inline function is replaced after the name is unique, that is, one call n times, there will be n temporary variables ... The volume of the program will increase violently.

The fifth chapter constructs, deconstruction, copies the semantics science

Object construction under the inheritance system

What steps are associated with the constructor call:

1. The data members initialization of the member initialization list is placed in the constructor function itself, in order of the Membs declaration order.

2. If a member is not in the initialization list, but it is in a default constructor, then the default constructor must be called (manually).

3. Before that, if class object has virtual table pointer (s), it must be set to the initial value, specifying the appropriate virtual table (s).

4. Until then, all the previous base class constructors must be called in the order of the base class declaration (not associated with the order of the initialization list).

If base class is listed in the initialization list, any explicitly specified arguments should pass past.

If base class is not listed in the initialization list, then the default constructor is called.

If base class is the second or subsequent base class under multiple inheritance, the this pointer must be adjusted.

5. Until then, all virtual base class constructors must be called, from left to right, from deepest to lightest.

If class is listed in the initialization list, then if there are any explicitly specified arguments, it should pass past, and if not listed in the initialization list, call default constructor.

In addition, the offset of each virtual base class Subobject in class must be accessible during the execution period.

If class object is the lowest class, a constructors may be called, and some mechanisms to support this behavior must be put in.

Object Replication semantics

When designing a class and specifying another class object with a class object, there are three options:

1. Do nothing and implement the default behavior.

2. Provide a explicit copy assignment operator.

3. Explicitly reject a class object assigned to another class object.

A class for the default copy assignment operator does not exhibit bitwise copy semantics in the following situations:

1. When a class base class has a copy assignment operator,

2. When a class member object and its class has a copy assignment operator,

3. When a class declares any virtual functions,

4. When class inherits a virtual base class.

Vptr Semantic Studies

When was the vptr initialized in constructor? After the base class constructors invokes the operation, but before the members initialization operation in the code supplied by the programmer or in the initialization list.

Deconstruction semantics

destructor is extended in the way:

The 1.destructor function itself is executed first.

2. If class has member class objects and then has destructor, then they are called in the reverse order of the declaration order.

3. If the object has a vptr in it, it is now reset to the appropriate base class virtual table.

4. If any direct (previous layer) Nonvirtual base classes has destructor, they are called in reverse order of declaration order.

5. If any virtual base classes has destructor, and the class currently being discussed is the last class, then they will be called in the reverse order of their original order.

Sixth. Semantics in the implementation period

The seventh chapter ...

Add: Type-up transformation and polymorphic confusion

To construct such an inheritance system:

Class Base {

Public:virtual ~base () {}

virtual void Show () {cout << "Base" << Endl;}

};

Class Derived:public Base {

Public:void Show () {cout << "Derived" << Endl;}

};

The subclass derived class overrides the Show method in base class base. Write the following test code:

Base b; Derived D;

B.show (); D.show ();

The result is:

Base

Derived

The base object calls the base method, and the derived object calls the derived method. Because the polymorphic mechanism is not turned on by invoking the member function directly with the object, the compiler can determine which show function to invoke, in the case of the two invocations, the compiler determines a unique entry address for each of them, based on the respective type of B and D. This is actually similar to an overloaded polymorphic, although these two show functions have different scopes. So that's it: Base b; Derived D; B.show (); b = D; B.show (); Now, a base object is assigned a subclass derived object.

That's it:

Base b; Derived D;

B.show (); b = D; B.show ();

Now, a base object is assigned a subclass derived object.

The result is:

Base

Base

For people who are familiar with Java, this is not understandable. But in fact, C + + is not Java, it's more like C. The meaning of "B = d" is not "let a reference to the base class refer to its subclass object" in Java, but instead "partition the base sub-object in the subclass object of the base class and assign the value to B". So, as long as the type of B is always base, then the B.show () call is always the show function in the base class; in other words, the compiler always takes the entry address of the show function in base as the entry address of the B.show (). It's not going to be a lot of use at all.

Rewrite polymorphism under single inheritance

Let's do it again:

Base b; Derived D;

Base *p = &b;

P->show ();

p = &d;

P->show ();

At this point, the result is the following:

Base

Derived

P is a pointer to a base class object, the first time it points to a base object, P->show () calls the show function of the base class, and the second time it points to a derived object, P->show () calls the show function of the derived class.

Summary: That is, only the pointer or the reference is the true polymorphism, the child object is assigned to the parent class object in fact type upward transformation ...

Personal think C + + easy confusing place (continuous update):

1.const and pointer modification issues

const char * A; A pointer to a const char

char Const *A; These two are constants of a point and cannot be changed

char * const A; First, A is the pointer and then the const

Const (char*) A; These two are constants of a pointer itself, and the pointer itself cannot be changed

In fact, it can be seen that if the const-modified char (that is, the type itself or the *variable of the pointer) is the pointer to the content is a constant, and vice versa is to modify the pointer itself. So we can summarize a way of recognizing that the type of the const (and, of course, only one side) is a type (the content that the pointer points to) is that the type variable itself is a constant (such as const char * A and Char const *a are char,*a on both sides).

Of course both are constants: const char * const A; the first const is a type constant, the second is a pointer constant. The same gives the const char &a; const char *a; used when passing parameters.

2. Combination of arrays and pointers

char * a[m]; This is an array of pointers, that is, each element is an array of pointers, and each element is initialized. A[M] is an array, each element of this array is char *, so you can extend char * to a one-dimensional array and then a[m] is a two-dimensional array. is actually a M-pointer.

char (*A) [N]; This is a pointer to the n char element, which is a pointer to an array, which is actually a pointer. Look at a variable (*a), which is a pointer to n elements, so it's just a one-dimensional array. You can think of char (*a) [N] as Char b[n].

In the same way, it can be distinguished by the principle of decoration, can be self-understanding. Dynamic allocation of specific two-dimensional arrays more highlights can check out one of my other blogs http://dsqiu.iteye.com/blog/1683142

Initialization of the 3.c++ variable

For a built-in type local variable is not initialized, but the address is assigned, the global variable is initialized by default. For class-type local variables (not explicitly initialized), default initialization (with default constructors, otherwise an error) is performed, but the built-in data members inside it are not initialized (if the default constructor is not initialized). Arrays are the same.

Deep Exploration of the C + + object model (Inside the C + +) Learning Notes

Related Article

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.