First of all before of writing some tips to write an efficient code using C++, we need to define the term of efficient code. There are multiple factors to measure the efficiency of any written code like (Speed, Memory Usage, Disk Access, Network use .. etc), so we can say that the efficient program is the program that completes its tasks as quickly as possible within the given circumstances, so the program can be efficient without being fast, if the application domain is mainly prohibitive to quick execution.
Regarding to professional C++ book 2005, there are two approaches to efficiency. The traditional one is to writing efficient program and optimizing, or improving the performance and this technique usually relates to Language-Level Efficiency: Some specific, independent code changes such as passing by reference, returning by reference, exception handling .. etc
The second approach is to think about the efficiency from the design point of view, and this named Design-Level efficiency: includes choosing efficient algorithms, avoiding unnecessary steps and computations, and selecting appropriate design and optimizations. In this post we’ll discuss the first approach which is Language-Level Efficiency.
As we previously mentioned, some specific, independent code changes such as passing by reference, returning by reference and so on and we’ll mention some tips and trick related to this.
- Handling Object Efficiently:
- Return by Reference
- Catch Exceptions by reference
- Avoid creating temporary objects
- Return Value Optimization
- Don’t Overuse costly language features
- Use Inline methods.
Handling Objects Efficiently
- Pass by reference:
Objects should rarely be passed by value to a function or method, as Pass-by-value incurs copying costs that are avoided by pass-by-reference. Assume that you have a class named “ClassA” and you’ll pass an instantiated object to some function to process it, you could write a function that takes a ClassA Object in the following way.
- Return by reference:
As you should pass the object by reference to functions, you should also return them by reference from functions in order to avoid unnecessarily copying of the object. And sometimes returning by reference is impossible , such as when you write overloaded operator+ and other similar operators. And take care “You should never return a reference or a pointer to a local object that will be destroyed when the function exits”
- Catch Exception by reference:
You should catch exceptions by reference in order to avoid an extra copy. exceptions are heavy in terms of performance.
- Avoid Creating Temporary Objects:
The compiler creates temporary, unnamed objects in several circumstances. for example after writing a global operator+ for a class.
In general, the compiler constructs a temporary object whenever your code converts a variable of one type to another type This rule applies mostly to function calls. For example, suppose that you write a function like this:
and you called this function like this: doSomething( 5.5) , The compiler constructs a temporary ClassTest object from 5.5 using the double constructor,which it passes to doSomething(), So generally try to avoid such of these cases in which the compiler is forced to construct temporary objects and you should at least be cognizant of the existence of this “feature” so you aren’t surprised by performance results.
- Return Value Optimization:
A function that returns an objects by value can cause the creation of a temporary object.
Finally, don’t worry about this issue because the compiler will optimize away the temporary variable in most cases. This optimization is called the return value optimization.
Don’t Overuse Costly language features
Several C++ features are costly in term of execution speed: exceptions, virtual methods, and Run-Time Type Information RTTI. If the code efficiency is an important factor for you, then you should consider avoiding these features. Unfortunately, support for exceptions and RTTI incurs performance overhead even if you don’t explicitly use the features in your program should be compiled without support for these features at all.
and the problem here when dynamic_cast<> fails at run time causing the program to generate segmentation violation exception.
Use Inline Methods
As most of us know that the code for an inline method is inserted directly into the code where it is called, avoiding the overhead of a function call. “However, remember that inlining requests by the programmer are only a recommendation to the compiler. It can refuse to inline the function that you want it to inline.”
On the other hand, some compilers inline appropriate functions and methods during their optimization steps, even if those functions aren’t marked with the inline keyword.