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

我怕爱的太早我们不能终老 提交于 2019-12-03 08:11:55

When the expression in the return statement is a non-volatile automatic duration object, and not a function or catch-clause parameter, with the same cv-unqualified type as the function return type, the resulting copy/move is eligible for copy elision. The standard also goes on to say that, if the only reason copy elision was forbidden was that the source object was a function parameter, and if the compiler is unable to elide a copy, the overload resolution for the copy should be done as if the expression was an rvalue. Thus, it would prefer the move constructor.

OTOH, since you are using the ternary expression, none of the conditions hold and you are stuck with a regular copy. Changing your code to

if(b)
  return x;
return y;

calls the move constructor.

Note that there is a distinction between RVO and copy elision - copy elision is what the standard allows, while RVO is a technique commonly used to elide copies in a subset of the cases where the standard allows copy elision.

cdhowie

Yes, there is. Don't return the result of a ternary operator; use if/else instead. When you return a local variable directly, move semantics are used when possible. However, in your case you're not returning a local directly -- you're returning the result of an expression.

If you change your function to read like this:

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

Then you should note that your move constructor is called instead of your copy constructor.

If you stick to returning a single local value per return statement then move semantics will be used if supported by the type.

If you don't like this approach then I would suggest that you stick with std::move. You may not like it, but you have to pick your poison -- the language is the way that it is.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!