Optimizing C++/Writing efficient code/Performance worsening features

When compared to C, C++ has some features that worsen efficiency if used inappropriately.

Some of these features are nevertheless quite efficient and can be used liberally when useful. However, their increased cost should be avoided when the feature is not needed.

Other features are instead quite inefficient and so should be used sparingly.

In this section, guidelines are presented for the avoidance of C++ features that worsen performance.

The operator
Call the  operator only when you want to notify a user of the failure of the current command.

Raising an exception has a very high cost when compared to a function call. It requires thousands of processor cycles. If an exception is raised only when a message is displayed on the user interface or written into a log file, there is a guarantee that it will not be performed too often without notice.

In contrast, if exceptions are made part of an algorithm, even if initially thought to be rare they may end up being performed too frequently.

member functions
'''Define the destructor as  if and only if the class contains at least one other   member function or if the class might be derived from (i.e. the class is intended for use as a base class). With the exception of destructors, do not declare functions as  unless you intend to override them.'''

Classes that have  member functions occupy more storage space than those without. Instances of classes having at least one  member function occupy more space (typically, a pointer and possibly some padding) and their construction requires more time (typically, to set the pointer) than instances of classes without   member functions.

In addition, every  member function has a slower call time than an identical non-  member function.

inheritance
Use  inheritance only when several classes must share the representation of a common base class.

For example, consider the following class definitions:

With such definitions, every C class object contains two distinct class A objects, one inherited from the B1 base class, and the other from the B2 class.

This is no problem if class A has no non- member variables.

If, instead, class A contains some member variables and you mean that such member variables are unique for every class C instance, you must use  inheritance, in the following way:

This situation is the only case when  derivation is necessary.

The member functions of the class A are somewhat slower to call on a C class object if  inheritance is used.

Templates of polymorphic classes
Do not define templates of polymorphic classes.

In other words, don't use the " " and the " " keywords in the same class definition.

Every time a class template is instantiated a copy is made of all member functions used. If such classes contain virtual functions, even their vtable and RTTI data is replicated. This data bloats the code.

Use of automatic deallocators
Use a memory manager based on garbage-collection or a kind of reference-counted smart-pointer (like  in the Boost library) only if you can prove its expediency for the specific case.

Garbage collection, or automatic reclamation of unreferenced memory, allows the programmer to leave out calls for memory deallocation and prevents memory leaks. However, one must implement garbage collection through a non-standard library since these features are not included in C++. In addition, code using garbage collection typically executes more slowly than code using explicit deallocation (when the  operator is explicitly called). In addition, when the garbage collector runs the rest of the program doesn't. This makes execution of the program less deterministic.

The C++98 standard library contains only one kind of smart-pointer,, that is quite efficient. Other smart-pointers provided by non-standard libraries, such as Boost, will be provided by the C++11 standard library. Smart-pointers rely upon reference-counting but are less efficient than simple pointers. For example,  is the standard Boost smart pointer. However, if the thread-safe version of Boost is used, the library has very poor performance for creation, destruction and copying of these pointers as it must guarantee mutual exclusion for these operations.

Usually, you should try to assign every dynamically allocated object to a single owner at design time. When such an assignment is difficult, for example if several objects tend to bounce the responsibility to destroy the object, it becomes expedient to use a reference-counted smart-pointer to handle the object.

The modifier
Only variables that are changed asynchronously by hardware devices should be defined .

The usage of the  modifier prevents the compiler from locating a variable in a register, even for a short time. This guarantees that all devices see the same variable, but slows down operations that access the variable.

does not guarantee that other threads will see the same values, as it does not force the compiler to generate the necessary memory barrier and lock instructions. Therefore, read and write access to a volatile value may be made out of order even on the same CPU (important in the case of interrupts and signals) and especially out of order across the memory cache and bus to other CPUs. You must use a proper thread or atomic memory API or write machine code to guarantee the proper order of operations for safe threading.

Ottimizzare C++/Scrivere codice C++ efficiente/Costrutti che peggiorano le prestazioni