move semantics in constructor in return statement

117 views Asked by At

I know that when returning a local in order to keep RVO we should allow the compiler to perform move elision by returning a value like so

std::vector<double> some_func(){
    std::vector<double> my_vector;
    //do something
    return my_vector;
}

rather than

std::vector<double> some_func(){
    std::vector<double> my_vector;
    //do something
    return std::move(my_vector);
}

However, if we are constructing an object in a return statement, do uses of std::move in the constructor either help, hinder, or do nothing to get efficiency or get in the compilers way?

As an example consider these two implementations

std::pair<std::vector<double>,std::vector<double> > some_func()
    std::vector<double> my_vec_a;
    std::vector<double> my_vec_b;
    //do something
    return std::make_pair(my_vec_a,my_vec_b);
}

and

std::pair<std::vector<double>,std::vector<double> > some_func()
    std::vector<double> my_vec_a;
    std::vector<double> my_vec_b;
    //do something
    return std::make_pair(std::move(my_vec_a),std::move(my_vec_b));
}

So

  1. In the first, will the compiler recognise that my_vec_a and my_vec_b will go out of scope and optimise the construction in the return statement?
  2. If so will the use of std::move in the second prevent that optimisation?
  3. Or will the second option be more efficient?
1

There are 1 answers

1
jwezorek On BEST ANSWER

This one is more efficient:

std::pair<std::vector<double>,std::vector<double> > some_func() { 
    std::vector<double> my_vec_a;
    std::vector<double> my_vec_b;
    //do something
    return std::make_pair(std::move(my_vec_a),std::move(my_vec_b));
}

without the calls to std::move the two vectors will be copied.

The problem, however, isn't the actual return. It's that the two vectors in the pair being constructed are being constructed from lvalues; the compiler can't choose to use a move-constructor there without you explicitly telling it to via std::move.