Consider the following scenario:
Your team provides libraries for use in other, unspecified applications. When designing your API, you have to consider the fact that not every customer will have access to the newest compiler.
Let's say you develop a
Vector
class that looks like this:
class Vector {
private:
size_t size_;
double* coords_;
public:
explicit Vector(size_t n); Vector(const Vector& v);
friend Vector add(const Vector& v1, const Vector& v2);
...
};
The implementation of the function
add
may look like this:
Vector add(const Vector& v1, const Vector& v2) {
Vector result(v1.size_);
for (size_t i = 0; i < v1.size_; ++i)
result[i] = v1[i] + v2[1];
return result;
}
Creating the local variable
result
will require a memory allocation. Returning it will then again force at least one more memory allocation, from invoking the copy constructor. Since this is a pretty basic function, you expect it to be called often, so performance matters, and memory allocations are not trivial, so you decide to take advantage of move semantics. However, you cannot know that every client using this API has access to a compiler with C++11 features, so you wrap the relevant code in a macro:
class Vector {
private:
size_t size_;
double* coords_;
public:
explicit Vector(size_t n); Vector(const Vector& v); #ifdef _HAS_CPP0X
Vector(const Vector&& v); #endif
...
};
Now the return statement in the add function can use the more efficient move constructor instead of the copy constructor. Clients with VS 2010 (or who explicitely define this macro because they have another brand of compiler that also supports it) will now be able to benefit from the new semantics. Yet, clients with an older version will not complain about the new syntax.