RTTI, virtual function and virtual base class's realization way, cost analysis and usage instruction

Source: Internet
Author: User
Tags error handling

Turn from: http://baiy.cn/doc/cpp/inside_rtti.htm


"Using the right features in the correct situation" is a basic standard for competent C + + programmers. To do this, you first need to understand how each feature in the language is implemented and its cost. This paper focuses on several new C + + features that have an impact on efficiency relative to traditional C: compile-time cost runtime overhead Documentation: C + + coding specification and guidance on the implementation of C + + exception mechanism and overhead analysis of multiprocessor environments and thread synchronization advanced Topics c++0x (C++11) new features reviews

Compared to the traditional C language, the additional overhead of C + + is reflected in the following two aspects: compile-time overhead

New features such as templates, class hierarchies, strong-type checking, and the large number of STL standard libraries that use these new features add to the compiler's burden. However, it should be noted that these new functions in the absence of reduction, or even (as a result of the template's inline ability) to improve the efficiency of program execution, significantly reduce the workload of the vast number of C + + programmers.

With a few seconds of CPU time in exchange for a few days of hard work, with savings in the future debugging and maintenance of the code time, this cost when counted as value.

Of course, when using these features, there are also a lot of optimization techniques. For example, when compiling a large software that relies extensively on a template library, several explicit instantiation directives can increase compilation speed by up to dozens of times times; the proper combination of partial specialization and full specialization not only optimizes the execution efficiency of the program, but also minimizes the volume of programs that instantiate a set of templates with multiple different parameters at the same time ...

  Run-time overhead

The
runtime overhead is probably one of the most concerned problems for programmers. In contrast to traditional C programs, new features that may introduce additional run-time overhead in C + + include: Virtual base class virtual function RTTI (dynamic_cast and typeID) exception object construction and destructor

About 4th: exception, for most modern compilers, Under normal circumstances (exceptions are not thrown), the code execution efficiency in the try block is as high as normal code, and the actual execution efficiency of the code may be further enhanced by the fact that it is no longer necessary to use traditional methods of judging errors by return values or function calls. The efficiency of throwing and catching exceptions is only slightly less efficient in some cases than the normal return of the function, not to mention that for a well-written program, there should be little chance of throwing and catching exceptions. For a detailed discussion of the use of exceptions, see the related sections in the body of C + + coding specifications and the implementation of the C + + exception mechanism and cost Analysis section.

and 5th, the construction and destructor overhead of an object does not always exist. For types that do not require initialization/destruction, there is no cost of construction and deconstruction, and in contrast to those types that need to be initialized/destroyed, the traditional C method is used, and at the very least the overhead is incurred. The point to note here is to try not to make the structure and destructor too bloated, especially in a class hierarchy. Always keep your constructs, destructors, and only the most necessary initialization and destruction operations, leaving to other methods and derived classes the actions that are not required for each (child) object.

In fact, for a good compiler, the various features of C + + are themselves tempered and optimized with C/assembler. It can be said that it is almost impossible to implement a C + + feature more efficiently than a compiler by using the assembler. If I could have done this, the warrior should have written a compiler to benefit programmers.

C + + is widely regarded as "inefficient" than C, and the root cause is that because programmers are not aware of the way in which certain features are implemented and the overhead they incur, caused them to use the wrong features in the wrong places. And these errors are basically focused on: treat the anomaly as another flow control mechanism, instead of using it for error handling only a class and/or its base class constructs, destructors are too bloated, contains many uninitialized/destroyed categories of code abuse or incorrectly uses RTTI, virtual functions, and virtual base class mechanisms

The first two points have been mentioned above, and the 3rd one is discussed below.

To illustrate the implementation of RTTI, virtual functions, and virtual base classes, here we first give a classic example of diamond inheritance and its implementation (for the sake of understanding, there is a deliberate omission of some trivial optimizations):


The virtual arrow in the figure represents the offset, and the solid arrow represents the pointer

The run-time cost of each feature is obtained from the above figure as follows:
Characteristics Time Overhead Space overhead
RTTI Several cosmetic comparisons and one access operation (possibly 1 or 2 cosmetic additions) One Type_info object per type (including type ID and class name), typically less than 32 bytes

 

virtual function One plastic addition and one pointer indirect reference A virtual table of each type, typically less than 128 bytes

A virtual table pointer, typically less than 8 bytes, for each object (in most cases)

 

Virtual base class When you access a data member of a virtual base class or its virtual function from a subclass of a virtual inheritance, you add two pointer indirect references and one cosmetic addition (in some cases, you can optimize for a pointer indirect reference). A virtual base class table of each type, typically less than 32 bytes

Several virtual base class table pointers per object, typically less than 8 bytes

When virtual functions are used at the same time, virtual base class tables can be merged into virtual tables (virtual table) , and each object's virtual base class table pointer (VBPTR) can also be omitted (just vptr). In fact, many implementations do this. The disadvantage of this is that you need to prepare multiple virtual tables for some intermediate types, such as B1, B2, and so on.

This is true if the specified type has only one virtual base class in its class hierarchy, most of which use a virtual base class. For example, if there is only one virtual base class in the above case, you can replace vbptr directly with the offset address of the virtual base class, which will save you a pointer indirect reference, thereby increasing your efficiency. Many compilers automatically turn on such optimizations.

In addition, this value is known at compile time because in many situations where you would otherwise need to access the offset field in a virtual table (for example, when you invoke certain virtual functions). The conversion from the base class object to the derived class this pointer can be completed by just one integer immediate number addition. Therefore, in the absence of any effect on time efficiency, you can retain only one vbptr pointer (meaning: The vbptr in the B2 in the above example can be omitted). This optimization method is often used with the previous mentioned, in the case of Tankuiki class to replace the vbptr directly with the virtual base class of the approach to use together to achieve a better balance between time efficiency and space efficiency, for example: VC often use such optimization method.

 

* where "each type" or "per object" refers to the type/object to which the attribute is used. This overhead is not increased for types and their objects that are not used for these features

It can be seen that the good legends about God's "drop pies when you're hungry and sleep off your wife" are pure rumors. Any artifact will not be perfect, there is always the choice of design, there is its adaptation of the occasion also has its not applicable places.

Each feature in C + + is gradually refined from the normal production life of the programmer. Using them in an incorrect situation is bound to cause logical, behavioral, and performance problems. For the above characteristics, it should only be used only if necessary and reasonable.

"dynamic_cast" is used to roam through the class hierarchy and to freely upward, downward, or cross coercion of pointers or references. "typeid" is used to get the exact type of an object or reference, unlike "dynamic_cast", it is usually an error to have "typeID" acting on the pointer, and to get the type_info of a pointer to an object, you should first dereference it (for example: "typeID (*p);" )。

Generally speaking, the problem that can solve with virtual function do not use "dynamic_cast", can use "dynamic_cast" to solve is not to use "typeID". Like what:



void
Rotate (in const cshape& is)
{
if (typeid (IS) = = typeID (ccircle))
{
// ...
}
else if (typeid (IS) = = typeID (ctriangle))
{
// ...
}
else if (typeid (IS) = = typeID (csqucre))
{
// ...
}

// ...
}

The above code with "dynamic_cast" write will be slightly better, of course, the best way is to define a virtual function named "Rotate" in Cshape.

Virtual functions are the least expensive and most commonly used mechanism in C + + Run-time polymorphic features. The benefits and effects of virtual functions here, you should pay attention to situations where performance is demanding, or frequent calls, to places where performance is more significant (such as thousands of calls per second, and very simple event handlers for their own content), use virtual functions with caution.

One particular point to note is that the invocation cost of a virtual function is equivalent to an indirect function call through a function pointer (for example, common in classic C programs, by pointing to a function pointer member in a struct, and by invoking a function in dll/so). A pointer indirect reference is trivial compared to the cost of the function call itself (saving the field-> pass parameter-> passing the return value-> recovery site). This makes it possible to afford the slightest extra overhead of virtual methods in most situations where functions can be used .

As a kind of object-oriented language supporting multiple inheritance, virtual base class is a necessary means to ensure the correct consistency of class hierarchy. However, you should try to avoid using the services provided by the base class frequently and where performance requirements are high. Virtual base classes can also be lifted when there are no data members in the base class. For example, in the above illustration, if the data member does not exist in the class "BB", then "BB" can be inherited as a normal base class by "B1" and "B2" respectively. This optimization relieves the overhead caused by the virtual base class on the premise of achieving the same effect. However, this optimization will also bring some problems: from "DD" Up to "BB" will cause ambiguity, the failure of the class hierarchy of the logical relationship.

The spatial overhead of the above features is generally acceptable, and there are some exceptions, such as the case where the storage layout needs to be compatible with the traditional C structure, where the alignment is considered, and when many objects need to be instantiated at the same time for a class that is small in size.

 

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.