The likelihood of writing efficient code is very small unless you understand the origins of temporary objects, their cost, and how to eliminate them when you can.
Only the first form of initialization is guaranteed, across compiler implementations, not to generate a temporary object. If you use forms 2 or 3, you may end up with a temporary, depending on the compiler implementation.
For example take the form:
This lead the compiler to generate the following code:
The overall cost here is two constructors and one destructor!
If you have function with the following definition:
An invocation of g(“message”) will trigger the creation of a temporary string object unless you overload g() to accept a char * as an argument:
In the following code fragment the operator+() expects two Complex objects as arguments. A temporary Complex object gets generated to represent the constant 1.0:
The problem is that this temporary is generated over and over every iteration through the loop. Lifting constant expressions out of a loop is a trivial and well-known optimization. The temporary generation in a = b + 1.0; is a computation whose value is constant from one iteration to the next. In that case, why should we do it over and over? Let’s do it once and for all:
Passing by value constructs temporary objects so passing them by reference optimizes the performance. Passing by value makes the following overheads:
- Call for the class constructor and calling for all class data members constructors.
- Calling the copy constructor of the class for the created temp variable.
- After the return, calling of the class destructor and destructors for all class data members.
The above chunk of code results in 6 function calls and creation of temporary variables. The below code acts as a solution:
As pointed out
But on a performance-critical path you need to forgo elegance in favor of raw performance. The second, “ugly” form is much more efficient. It creates zero temporaries.
- A temporary object could penalize performance twice in the form of constructor and destructor computations.
- Declaring a constructor explicit will prevent the compiler from using it for type conversion behind your back.
- A temporary object is often created by the compiler to fix a type mismatch. You can avoid it by function overloading.
- Avoid object copy if you can. Pass and return objects by reference.
You can eliminate temporaries by using <op>= operators where <op> may be +, -, *, or /.