When lvalues ​​are moved and not copied in C ++?

Given the following:

Foo getFoo() { Foo result = doSomeWork(); return result; } 
  • Does C ++ guarantee that the result will be moved, not copied? Or, to put it another way, writes return std::move(result) too much?

  • Are there any (other) situations where the standard indicates that the lvalue will silently move instead of copying, in the absence of an explicit expression std::move ?

Notes:

  • Suppose Foo is constructive in design.

  • Refusal to copy / move elision, which can be applied additionally.

+6
source share
2 answers
  • Although this step may be undone, Yes. A copy will never happen if a move constructor is available. I will quote this paragraph again for clarity. [Class.copy] / 32:

    When the criteria for performing the copy / move operation are met , but not to declare an exception, but rather the object to be copied, this is denoted by lvalue, or when the expression in the return statement is (possibly in brackets) an id expression that names the object with automatic storage time declared in the body or Parameter-declaration-sentence of the innermost include function or lambda expression, overload resolution to select a constructor for the copy is first performed as if the object was assigned an Rvalue . If the first overload resolution fails or did not exist, or if the type of the first parameter of the selected constructor is not an rvalue reference to the type of objects (possibly cv-qualified), the overload resolution is executed again, considering the object as an lvalue. [Note. This two-step overload resolution should be performed regardless of whether copying occurs. This determines the calling constructor if elision fails, and the selected constructor should be available, even if the call is omitted. - final note]

    Using std::move not redundant, but it actually prevents copying, [class.copy] / 31:

    - in the return expression in the function with the return type of the class, when the expression is the name of a non-volatile automatic object [..]

  • Yes, one situation. Again, I assume that you meant that if copying is not performed, the move is performed (copying should be applicable if the lvalue is moved, sa). Consider this:

     A a; throw a; 

    The criteria are met:

    - in the throw expression, when the operand is the name of a non-volatile automatic object (except for a function or catch-clause parameter), the volume of which does not go beyond the inner including a try-block (if any), the copy / move operation from the operand to the exception object (15.1 ) the construction of an automatic object directly into an exception object can be omitted

    Demo
    This is the only case where an lvalue is moved rather than copied; In two other cases, only temporary sections are excluded for copying, which are not attached to the link (which should therefore be indicated by prvalues) and the material declaration of exclusion, which is not interesting here because it covers the object of the exception that we do not see.

+4
source

I think this is an example of optimizing the return value. http://en.wikipedia.org/wiki/Return_value_optimization The compiler does not copy or move an object at all, but defines it. So no, I would not write return std::move(result) , it cannot even optimize the compiler.

0
source

Source: https://habr.com/ru/post/980272/


All Articles