C++ is all about object oriented programming. Combined with templating, objects become generic and âÂ?Â?reusable.âÂ?Â? Or at least thats what your typical beginning computer science instructors will tell you in high school or college. The truth is that while objects appear reusable to you, they are rarely actually reused by your compiler. This article, the first in a series on C++ optimizations, discusses a simple way to reduce your application’s code size while improving execution speed.Lets start out the article with a typical C++ class declaration for an Array template.
template < class T >
class Array {
public:
T & operator[](int n) { return m_elements[n]; }
... // Other methods
private:
T * m_elements;
};
Lets say your program needs an array of integers, you would declare an instance as:
Array< int > myIntArr;
Then later in code, you find out that you need an array of unsigned integers:
Array< unsigned int > myUnsignedIntAr;
When you compile your program in C++, the compiler actually creates two full working copies of the Array class. One instance is for the integer data type, the other for the unsigned integer data type. This naturally doubles the size of your compiled code. As your C++ application gets more and more complex, the amount of binary code to implement all instances of the Array class increases significantly.
As code size goes up, you can expect performance to go down for a number of reasons. The two big ones that I often talk about is that it takes longer to initially load code from the hard drive and your CPU cannot keep very much code in its on-die cache so it has to swap it out to the main system memory.
Luckily for us C++ has a little known and rarely used set of features that can not only help us reduce our application’s code size, but also improve cache-friendliness.
The first feature that we’ll discuss is the concept of inline-casting with template specialization. When you have two data types, which consume the same amount of memory, you can do this method. Here is an example of how it works:
If you have an Array< int >
and Array< unsigned int >
both used by your program, we’ll âÂ?Â?wrapâÂ?Â? one implementation within the other. First you declare your generic Array template which will handle Array<int>
and then you declare a special cast version which will handle Array<unsigned int>
.
The basic array with an example method to retrieve a reference to element n
of the array.
template < class T >
There are a number of options available to people in the long run. discount here order cialis This rigidity enables the man to penetrate their partner and orgasm But an early climaxing can be another reason for having the condition is the use of some medicines! djpaulkom.tv discount viagra usa This should be the treatment plan for any man who is unfortunate to suffer from impotency, it is the state in which the penis do not get erect for attaining maximum sexual pleasure. Many pastors are unable to reach large congregations, as they cannot find any of those magical tablets in the first instance. cialis viagra levitra buying cialis in australia Reproduction is a biological process in which a man is unable to get and maintain an erection even after proper sexual stimulation. class Array {
public:
T & operator[](int n) { return m_elements[n]; }
... // Other methodsprivate:
T * m_elements;};
#define INTERNAL_TYPE int
#define EXTERNAL_TYPE unsigned inttemplate <>
class Array< EXTERNAL_TYPE > {
public:
inline EXTERNAL_TYPE & operator[](int n) { return (EXTERNAL_TYPE) m_array[n]; }
... // Other methods
private:
Array< INTERNAL_TYPE > m_array;
};
When your compiler sees the above code, it declares a generic template for Array of type T
, where
T
is any given type. The type unsigned int
is an exception though, because it sees that the template has been specialized to have a different implementation than the generic Array<T>
. We actually utilize Array<T>
from within Array<unsigned int>
for the member data called m_array
.
Most compilers will honor your inline
request and therefore automatically map down any usage of Array<unsigned int>
to actually be the exact same binary code as
Array<int>
when you do this.
The above example only demonstrates one relatively simple method of the Array class, but some methods of your container data type Array<T>
might be amazingly complex or produce large amounts of CPU instructions during compiling. Regardless of how complex and large the implementation of Array<int>
becomes, you can count on your inline cast specialization of each of Array’s methods to add little or no code to your final binary application.