Can this C++ code be changed or improved with move semantics?

Viewed 200
struct big_struct{
    vector<int> a_vector;
    map<string, int> a_map;
};

big_struct make_data(){
    big_struct return_this;
    // do stuff, build that data, etc
    return return_this;
}
int main(){

    auto data = make_data();
}

I have seen move semantics applied to constructors, but in this bit of code, I'm wondering if the big struct is copied entirely when returned or not. I'm not even sure it is related to move semantics. Does C++ always copies this kind of data, or is it optimized? Could this code be change or improved?

What about a function that returns a vector or a map? Is that map/vector copied?

2 Answers

You don't need to change anything. What you have right now is the rule of zero. Since both std::map and std::vector are moveable your class automatically gets move operations added to it.

Since return_this is a function local object it will be treated as an rvalue and it will either be moved for you or NRVO will kick in and no move or copy will happen.

Your code will either produce a default construction call for return_this and a move constructor call for data or you will see a single default constructor call for data (NRVO makes return_this and data the same thing).

As stated here, your class actually has a move-constructor (implicitly generated one), so it shouldn't be copied in your code, at least once (in main).

One problem is, what you're relying upon is called NRVO, and compilers are not required to implement it (unlike its happier simpler brother, RVO.) So your struct has a chance, quite very small, to be copied in the return statement—but so small that return-by-move (like return std::move(return_this);) is never actually recommended. Chances are quite high the NRVO will actually be applied if you really have a single return statement in your function that returns a single named object.

Related