"The committee shall make no rule that prevents C++ programmers from 
"shooting themselves in the foot."

First Amendment to the C++ Standard quoted by Thomas Becker
http://thbecker.net/articles/rvalue_references/section_04.html  



Therefore we should use std::move() with extra care.


-- Usually std::move() has positive effect on performance,
   as many standard algorithm utilize move semantics.

-- Sometimes we have to use std::move().
   There are types moveable but not copyable:

   std::unique_pointer
   std::fstream
   std::thread




X&& f();

void g(X&& arg_)
{
  X var1 = arg_;   // copy or move?     
  X var2 = f();    // copy or move?
}


Since arg_ is declared as rvalue reference we might think that here
X::X(X&& rhs) will be called. But not always:

Things that are declared as rvalue reference can be lvalues or rvalues.
Anything has a "name" is an "lvalue" otherwise it is an "rvalue".

Therefore in the var1 example above X::X(const X& will be called),
and in the var2 example X::X(&&) is called.

Philosophy:
After X var1 = arg_; arg_ is still in scope and can be available.


X&& f();

void g(X&& arg_)
{
  X var1 = arg_;   // copy  X::X(const X&)
  X var2 = f();    // move  X::X(X&&)
}                  // arg_ goes out of scope here





void f()
{
  X var1;
  X var2 = std::move(var1);

  var1.g();  // var1 is undefined, but destructable
             // which operations are valid here for v1?
}


// example based on Scott Meyers: Effective Modern C++
// modified a bit



#include <iostream>

struct MyString
{
  MyString() { std::cerr << "defCtor" << std::endl; }
  MyString(const MyString& rhs) { std::cerr << "copyCtor" << std::endl; }
  MyString(MyString&& rhs) { std::cerr << "moveCtor" << std::endl; }
};

class MoveConstr
{
public:
  MoveConstr( MyString s) : value(std::move(s)) { }
private:
  MyString value;
};

int main()
{
  MoveConstr mc(MyString());
  return 0;
}


$ ./a.out
$


//?????????????




"Most vexing parse!!!"



MoveConstr mc(MyString())
   -->  Function mc returning MoveConstr has one parameter
        a pointer to function returning MyString having no parameter
        without parameter name.


MoveConstr mc(MyString())  ===  MoveConstr mc(MyString (*)())





$ clang++ -std=c++11 -Wvexing-parse m1.cpp
m1.cpp:21:16: warning: parentheses were disambiguated as a function declaration
      [-Wvexing-parse]
  MoveConstr mc(MyString());
               ^~~~~~~~~~~~
m1.cpp:21:17: note: add a pair of parentheses to declare a variable
  MoveConstr mc(MyString());
                ^
                (         )
1 warning generated.





#include <iostream>

struct MyString
{
  MyString() { std::cerr << "defCtor" << std::endl; }
  MyString(const MyString& rhs) { std::cerr << "copyCtor" << std::endl; }
  MyString(MyString&& rhs) { std::cerr << "moveCtor" << std::endl; }
};

class MoveConstr
{
public:
  MoveConstr( MyString s) : value(std::move(s)) { }
private:
  MyString value;
};

int main()
{
  MoveConstr mc((MyString()));
  return 0;
}


$ ./a.out
defCtor
moveCtor
$





#include <iostream>

struct MyString
{
  MyString() { std::cerr << "defCtor" << std::endl; }
  MyString(const MyString& rhs) { std::cerr << "copyCtor" << std::endl; }
  MyString(MyString&& rhs) { std::cerr << "moveCtor" << std::endl; }
};

class MoveConstr
{
public:
  MoveConstr( const MyString s) : value(std::move(s)) { }  // const MyString
private:
  MyString value;
};

int main()
{
  MoveConstr mc((MyString()));
  return 0;
}


$ ./a.out
defCtor
copyCtor
$





#include <iostream>

struct MyString
{
  MyString() { std::cerr << "defCtor" << std::endl; }
  MyString(const MyString& rhs) { std::cerr << "copyCtor" << std::endl; }
  MyString(MyString&& rhs) { std::cerr << "moveCtor" << std::endl; }
};

class MoveConstr
{
public:
  MoveConstr( const MyString& s) : value(std::move(s)) { }  // const MyString&
private:
  MyString value;
};

int main()
{
  MoveConstr mc((MyString()));
  return 0;
}


$ ./a.out
defCtor
copyCtor
$






If-it-has-a-name-rule:


class Base
{
public:
  Base(const Base& rhs); // non-move semantics
  Base(Base&& rhs);      // move semantics      
  :
};


class Derived : public Base
{
  Derived(const Derived& rhs);  // non-move semantics
  Derived(Derived&& rhs);       // move semantics
  :
};


Derived(Derived const & rhs) : Base(rhs)  // non-move semantics
{
  // Derived-specific stuff
}

// wrong
Derived(Derived&& rhs) : Base(rhs) // wrong: rhs is an lvalue
{
  // Derived-specific stuff
}

// good
Derived(Derived&& rhs) : Base(std::move(rhs)) // good, calls Base(Base&& rhs)
{
  // Derived-specific stuff
}




Performance




#include <utility>

class X
{
public:
  X(int sz_);
  X(const X& rhs_);
  X(X&& rhs_);
  ~X();
private:
  int _size;
  int *_v;
};

X::X(int sz_) : _size(sz_), _v(new int[_size])
{
  // dont care to initialize _v[]
}
X::X(const X& rhs_) : _size(rhs_._size), _v(new int[_size])
{
  for(int i = 0; i < _size; ++i)
    _v[i] = rhs_._v[i];
}

X::X(X&& rhs_) : _size(rhs_._size)
{
  _v = rhs_._v;
  rhs_._size = 0;
  rhs_._v = 0;
}
X::~X()
{
  delete [] _v;
}


// with copy
int main()
{
  for( int i = 0; i < 1000; ++i)
  {
    X x(1000000);
    X y(x);
    //X y(std::move(x));
  }
  return 0;
}

$ time ./a.out
real    0m18.324s
user    0m8.201s
sys     0m5.728s



// with move
int main()
{
  for( int i = 0; i < 1000; ++i)
  {
    X x(1000000);
    //X y(x);
    X y(std::move(x));
  }
  return 0;
}

$ time ./a.out
real    0m4.667s
user    0m0.700s
sys     0m2.980s



// with common sense
int main()
{
  X x(1000000);
  for( int i = 0; i < 1000; ++i)
  {
    X y(x);
    //X y(std::move(x));
  }
  return 0;
}

$ time ./a.out
real    0m11.662s
user    0m7.528s
sys     0m3.188s



// being too greedy :)
int main()
{
  X x(1000000);
  for( int i = 0; i < 1000; ++i)
  {
    //X y(x);
    X y(std::move(x)); // bad: further y's will be empty...
  }
  return 0;
}


// ============== another version: slow down the copy =======

X::X(const X& rhs_) : _size(rhs_._size), _v(new int[_size])
{
  for(int i = 0; i < _size; ++i)
    for (int j = 0; j < 1000; ++j ) // make it measurable
      _v[i] = rhs_._v[i];
}


int main()
{
  X x(1000000);
  X y(x);
  //  X y(std::move(x)); 
  return 0;
}

$ g++ -std=c++0x -pedantic -Wall r.cpp

time ./a.out
real    0m6.545s
user    0m6.124s
sys     0m0.028s

$ g++ -O3 -std=c++0x -pedantic -Wall r.cpp

time ./a.out
real    0m2.024s
user    0m1.840s
sys     0m0.024s


int main()
{
  X x(1000000);
  // X y(x);
  X y(std::move(x));
  return 0;
}

$ g++ -std=c++0x -pedantic -Wall r.cpp
time ./a.out
real    0m0.015s
user    0m0.004s
sys     0m0.004s

$ g++ -O3 -std=c++0x -pedantic -Wall r.cpp
time ./a.out
real    0m0.015s
user    0m0.000s
sys     0m0.012s




// ================== another version: returning a local ===================

X f()
{
  X x(10000000);
  //
  return x;
  // return std::move(x);
}

int main()
{
  X y(f());
  return 0;
}

$ time ./a.out
real    0m0.043s
user    0m0.020s
sys     0m0.016s

X f()
{
  X x(10000000);
  //
  // return x;
  return std::move(x);
}

int main()
{
  X y(f());
  return 0;
}


$ time ./a.out
real    0m0.039s
user    0m0.016s
sys     0m0.016s




There is almost no difference since modern compilers apply RVO
(return value optimization). That means, local x inside f() is
created in place of y.


In some cases, the performance even worst when using std::move()!


David Abrahams has an article on this:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/