mardi 23 décembre 2014

Can we use the return value optimization when possible and fall back on move, not copy, semantics when not?

Is it possible to write C++ code where we rely on the return value optimization (RVO) when possible, but fall back on move semantics when not? For example, the following code can not use the RVO due to the conditional, so it copies the result back:



#include <iostream>

struct Foo {
Foo() {
std::cout << "constructor" << std::endl;
}
Foo(Foo && x) {
std::cout << "move" << std::endl;
}
Foo(Foo const & x) {
std::cout << "copy" << std::endl;
}
~Foo() {
std::cout << "destructor" << std::endl;
}
};

Foo f(bool b) {
Foo x;
Foo y;
return b ? x : y;
}

int main() {
Foo x(f(true));
std::cout << "fin" << std::endl;
}


This yields



constructor
constructor
copy
destructor
destructor
fin
destructor


which makes sense. Now, I could force the move constructor to be called in the above code by changing the line



return b ? x : y;


to



return std::move(b ? x : y);


This gives the output



constructor
constructor
move
destructor
destructor
fin
destructor


However, I don't really like to call std::move directly.


Really, the issue is that I'm in a situation where I absolutely, positively, can not call the copy constructor even when the constructor exists. In my use case, there's too much memory to copy and although it'd be nice to just delete the copy constructor, it's not an option for a variety of reasons. At the same time, I'd like to return these objects from a function and would prefer to use the RVO. Now, I don't really want to have to remember all of the nuances of the RVO when coding and when it's applied an when it's not applied. Mostly, I want the object to be returned and I don't want the copy constructor called. Certainly, the RVO is better, but the move semantics are fine. Is there a way to the RVO when possible and the move semantics when not?


Aucun commentaire:

Enregistrer un commentaire