Page Collection for ^2012-05-08

2012-05-08-1 CPlusPlus11

Changes to old habits - you need to move to!

With moving available the old habit of always passing non native types as const to ref is not necessary any more. Moving makes call by value and return by value good alternatives.

From my experience return by value was something that was used a lot although the overhead of a copy. Partly because functions are easier to understand that way, return values in parameters is not taught as a good design, and partly because of the return value optimization sometimes got away without a copy anyway and still do!

With C++11 we can safely use call by value when we want that even for complex types. So we should write code like this from now on:

   string manipulate(string s)
   {
      <... perform some manipulation on s ...>
      return s;
   }

Since we are going to change the value on the string we might as well use call by value and change that. The modified value is then returned. The move ctor will kick in an see to that no unnecessary copy is needed.

2012-05-08 CPlusPlus11

Still moving on

One obvious place for moving objects instead of copying is when making a swap. It is a common operation so there is even a library function for that, std::swap. When used with types that implements the move-ctor and move assignment operator it looks like this.

First we define the move members to illustrate our example.

   ...
   Class(Class&& c) { cout << "Class&& ctor" << endl; }
   Class& operator=(Class&& c) { cout << "Class&& operator=" << endl; return *this; }
   ...

Running this code

   Class c1;
   Class c2;
   swap(c1, c2);

Produces this output:

   Class&& ctor
   Class&& operator=
   Class&& operator=

This tells us that first one of the objects is moved somewhere. A temporary lvalue to hold the value as party of the swap. Then there are two move assignments to get the values back in their new place.

If we would implement this ourselves it could look like this:

   Class temp(move(c1));
   c1 = move(c2);
   c2 = move(temp);

This introduces the new function std::move. It can look a little strange but its job is no more and no less than to typecast its argument into an rvalue reference. This will enable the use of the move members and the output is the same as the example above.

The move feature has been implemented in the standard library containers. So code like this:

   vector <Class> v;
   v.push_back(Class());

will use the move ctor when the new Class object is pushed into the vector. This was legal code before C++11 so this is an example where old code will benefit from the new features without any changes.