mardi 27 mars 2018

move semantics and copy-elision

I know has been asked several times, I read several tutorial about it but still I can't figure out an answer.

Let's have the typical class

class Foo
{
public:
   Foo()                : i_(0) { std::cout <<  "Foo Empty ctor" << std::endl; }
   Foo(const Foo& foo)  : i_(foo.i_) { std::cout <<  "Foo Copy ctor" << std::endl; }
   Foo(int i)           : i_(i)  { std::cout <<  "Foo Param ctor" << std::endl; }
   Foo(Foo&& foo)       : i_(foo.i_) { foo.i_ = 0; std::cout <<  "Foo Move ctor" << std::endl; }
   Foo(const Foo&& foo) : i_(foo.i_) { std::cout <<  "Foo const Move ctor" << std::endl; }

   ~Foo() { std::cout << "Foo " << i_ << " destroyed\n"; }

   Foo& operator=(Foo&& other)
   {
      i_ = std::move(other.i_);
      std::cout << "Foo Move assigned\n";
      return *this;
   }
private:
   int i_;
};

Foo getFoo()
{
   return Foo(99);
}


int main()
{
   Foo f1;
   Foo f2(5);
   Foo f3(f2);
   Foo f4(Foo(4));
   Foo f5(std::move(Foo(6));
   Foo f6 = getFoo();
   Foo f7 = Foo(1);
}

Output

// f1
Foo Empty ctor

// f2 
Foo Param ctor

// f3
Foo Copy ctor

// f4 - copy elision
Foo Param ctor

// f5
Foo Param ctor
Foo Move ctor

// f6 - copy elision
Foo Param ctor

// f7 - copy elision
Foo Param ctor

So, except when I call explicitly the move operator, the copy elision optimization do the same work even if do not declare move semantics.

1 - In case when we are not dealing with pointers and I'm not going to call an explicit std::move (so I suppose an implicit call like in the examples) does it have sense declaring move semantics if the copy elision do the same without is?

2 - Does have generally sense declaring move semantics for small classes with simple data? Does it have real advantages?

Aucun commentaire:

Enregistrer un commentaire