Optimizing C++/Code optimization/Allocations and deallocations

Even using a very efficient allocator, the allocation and deallocation operations take a significant time, and often the allocator is not very efficient.

In this section some techniques are described to decrease the total number of memory allocations, and their corresponding deallocations. They are to be applied only in bottlenecks, that is after having measured that the large number of allocations has a significant impact on performance.

Move allocations and deallocations
Move before bottlenecks memory allocations, and after bottlenecks the matching deallocations.

Variable length dynamic memory management is much slower than automatic memory management.

Analogous optimization is to be done for operations causing allocations indirectly, as the copy of objects which, directly or indirectly, own dynamic memory.

The function
Before adding elements to a  or to a   object, call its member function   with a size big enough for most cases.

If objects are repeatedly added to a  or   object, several costly reallocations are performed. To avoid such reallocations, it is enough to initially allocate the required space.

Keep s capacity
To empty a  object without deallocating its memory, use the statement  ; to empty it and deallocate its memory, use the statement  .

To empty a  object, there also exists the   member function, but, the C++ standard does not specify whether or not this function preserves the allocated capacity of the.

While the standard does not specify if the capacity is altered, further testing points towards the capacity remaining unchanged. On top of this, C++11 has a "shrink_to_fit" function for this behavior.

If you are repeatedly filling and emptying a  object, and thus you want to to avoid frequent reallocations, perform the emptying by calling the   member function, which, according to the standard, preserves the capacity of the object. If instead you have finished using a large  object, and you may not use it again or you are going to use it with substantially fewer elements, you should free the object's memory by calling the   function on a new empty temporary   object.

function overload
For every copyable concrete class  which, directly or indirectly, owns some dynamic memory, redefine the appropriate   functions.

In particular, add to the class  member function having the following signature:

and add the following non-member function in the same namespace that contains the class :

and, if the class is not a class template, add also the following non-member function in the same file that contains the class  definition:

In the standard library, the  function is called frequently by many algorithms. Such function has a generic implementation and specialized implementations for various types of the standard library.

If objects of a non-standard class are used in a standard library algorithm that calls  on them, and the   function is not overloaded, the generic implementation is used.

The generic implementation of the  function causes the creation and destruction of a temporary object and the execution of two object assignments. Such operation take much time if applied to objects that own dynamic memory, as such memory is reallocated three times.

The ownership of dynamic memory may be even only indirect. For example, if a member variable is a  or a , or is an object that contains a   or   object, the memory owned by these objects is reallocated every time the object that contains them is copied. Therefore, even in these cases the  function is to be overloaded.

If the object doesn't own dynamic memory, the copy of the object is much faster, and however it is not noticeably slower than using other techniques, and so no  overload is needed.

If the class is not copyable or abstract, the  function must never be called on object of such type, and therefore also in these cases no   function is to be redefined.

To speed up the function, you have to specialize it for your class. There are two possible ways to do that: in the same namespace of the class (that may be the global one) as an overload, or in the namespace  as a specialization of the standard template. It is advisable to define it in both ways, as, first, if it is a class template only the first way is possible, an then some compilers do not accept or accept with a warning a definition only in the first way.

The implementations of such functions must access all the members of the object, and therefore they need to call a member function, that by convention is called again, that does the actual work.

Such work consists in swapping all the non-static members of the two objects, typically by calling the  function on them, without qualifying its namespace.

To put the function  into the current scope, the function must begin with the statement:

Ottimizzare C++/Ottimizzazione del codice C++/Allocazione e deallocazione