std::move to a function

452 views Asked by At

I have this example code:

#include <iostream>

class Struct {
public:
   Struct() { std::cout << "0" << std::endl; }
   Struct(Struct&) { std::cout <<"1"<<std::endl;}
   Struct(const Struct&) { std::cout << "2" << std::endl; }
};

class Struct2 {
public:
    Struct s;

    Struct2() {}
    void setMember(const Struct& aux) { s = aux; }
};

int main()
{
    Struct s;
    Struct2 s2;
    s2.setMember(s);
}
// http://coliru.stacked-crooked.com/a/dd57e8af23f6db4b

Doubt 1:

It is printting two 0, because the constructor in the main and the construct of the member of Struct2.

The thing is, I was expecting three 0, because the "setMember" is receiving a copy of 's', right? What is happening then?

Doubt 2:

I was thinking in putting this:

s2.setMember(std::move(s)); 

As I won't use 's' again, but the setMember does not have '&&' specified, is it ok? Do i have to also do this? :

s = std::move(aux);

Or with just the main one is enough?

Doubt 3 :

std::vector<A> vectorA;

int main()
{
    A a;
    // modifies a ...
    vectorA.push_back(std::move(a));
}

Is it correct? Am I optimizing anything moving 'a'? It will not be used anymore and I want to keep it in the vector

Thanks

1

There are 1 answers

3
Bartek Banachewicz On BEST ANSWER

because the "setMember" is receiving a copy of 's', right?

Well, no. It's receiving a const& and copies on assignment operator. Since you haven't overloaded the assignment operator, nothing is printed out.


s2.setMember(std::move(s));

This won't solve anything; std::move will just cast s to rvalue, but inside of the function it's still a const&.


Rule of thumb: pass-by-value, move out inside:

void setMember(Struct aux) { s = std::move(aux); }

That way it will "automagically" work; copying lvalues on interface / moving rvalues into the parameter value, and then moving the parameter value into the actual object member.

Of course to make optimal use of that machinery, you need an rvalue passed there, so...

Struct s;
Struct2 s2;
s2.setMember(std::move(s));

Or perhaps...

s2.setMember(Struct());

That being said, your old code won't break.


As for the third example, yes, this is OK, altough I'd probably either

  • move the change to a to another function and push_back(function())
  • move the changes to a to As constructor and use emplace_back