In C++0x, you can overload functions based on the value categories of arguments and similarly have lvalueness detected by template argument deduction. You can also have an rvalue bound to an rvalue reference and modify the rvalue through the reference. This enables a programming technique with which you can reuse the resources of expiring objects and therefore improve the performance of your libraries, especially if you use generic code with class types, for example, template data structures. Additionally, the value category can be considered when writing a forwarding function.
When you want to optimize the use of temporary values, you can use a move operation in what is known as destructive copying. Consider the following string concatenation and assignment:
std::string a, b, c;
c = a + b;
In this program, the compiler first stores the result of a + b in an internal temporary variable, that is, an rvalue.
string& operator = (const string&)
With
this copy assignment operator, the assignment consists of the following
steps:To avoid the needless duplication of the temporary variable, you can implement an assignment operator that moves the variable instead of copying the variable. That is, the argument of the operator is modified by the operation. A move operation is faster because it is done through pointer manipulation, but it requires a reference through which the source variable can be manipulated. However, a + b is a temporary value, which is not easily differentiated from a const-qualified value in C++ before C++0x for the purposes of overload resolution.
string& operator= (string&&)
With
this move assignment operator, the memory allocated for the underlying
C-style string in the result of a + b is assigned
to c. Therefore, it is not necessary to allocate
new memory to hold the underlying string in c and
to copy the contents to the new memory.string& string::operator=(string&& str)
{
// The named rvalue reference str acts like an lvalue
std::swap(_capacity, str._capacity);
std::swap(_length, str._length);
// char* _str points to a character array and is a
// member variable of the string class
std::swap(_str, str._str);
return *this;
}
However, in this implementation, the memory originally
held by the string being assigned to is not freed until str is
destroyed. The following implementation that uses a local variable
is more memory efficient:string& string::operator=(string&& parm_str)
{
// The named rvalue reference parm_str acts like an lvalue
string sink_str;
std::swap(sink_str, parm_str);
std::swap(*this, sink_str);
return *this;
}