Writing Efficient C++

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.

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:
    • Pass-By-Reference
    • 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.

  1. void TestClassA( const ClassA& classAObj)
  2. {/*Test Code*/}

instead of

  1. void TestClassA( ClassA classAObj)
  2. {/*Test Code*/}
  • 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.

  1. try{
  2.     …
  3. }
  4. catch(CustomException &e){
  5.     …
  6. }
  • Avoid Creating Temporary Objects: 

    The compiler creates temporary, unnamed objects in several circumstances. for example after writing a global operator+ for a class.

  1. class ClassTest{
  2. private:
  3.     int m_value;
  4. public:
  5.     ClassTest(){}
  6.     ClassTest(double &initialValue):m_value(initialValue){}
  7.     void Set(int value)
  8.     {m_value = value;}
  9. };
  10. const ClassTest operator+(const ClassTest& lhs, const ClassTest& rhs)
  11. {
  12.     ClassTest test;
  13.     test.Set(lhs.m_value+ rhs.m_value);
  14.     return (test);
  15. }

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:

  1. void doSomething(const ClassTest& s);

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.

    1. Person CreatePerson()
    2. {
    3.     Person newP;
    4.     return (newP);
    5. }

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.

  1. Class base
  2. {
  3. public:
  4.     base() {}
  5.     virtual ~base() {}
  6. };
  7. class derived : public base {};
  8. int main(int argc, char** argv)
  9. {
  10.     base* b = new derived();
  11.     derived* d = dynamic_cast<derived*>(b); // Use RTTI.
  12.     if (d == NULL) {
  13.         throw exception(); // Use exceptions.
  14.     }
  15.     return (0);
  16. }

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.

  1. inline void Hello();

3 thoughts on “Writing Efficient C++

  1. Keep up the good work (Y)
    Also, a good performance tip is to use initialization lists in constructors instead of using assignment when initializing user-defined data types because this avoids creating a temporary object when invoking the assignment operator and instead uses the actual object you sent to initialize the object. For more details, check this FAQ about the comparison between initialization lists and assignments http://www.parashift.com/c++-faq/init-lists.html

    There is also a good write-up about inline functions here http://www.parashift.com/c++-faq/inline-and-perf.html

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s