Should we write `std :: move` in cases where RVO cannot be done?

It is known that std::moveit should not be applied to the values ​​of the returned function, since this can prevent RVO (optimization of the return value). I am interested in the question of what should we do if we know for sure that RVO will not happen.

This is what the C ++ 14 standard says [12.8 / 32]

When the criteria for performing the copy / move operation are satisfied, but not for declaring an exception, and the object to be copied is denoted by lvalue, or when the expression in the return expression is (possibly in brackets) an id expression that names the object since the time of automatic storage specified in the body or parameter-declaration-sentence of the innermost closing function or lambda-expression, overload resolution to select the constructor for the copy is first executed as if the object was assigned an Rvalue. If the first overload resolution fails or fails, or if the type of the first parameter of the selected constructor does not rvalue the object type (possibly cv-qualified), the overload resolution is executed again, treating the object as naming. [Note.This two-step overload resolution should be performed regardless of whether copying occurs. It defines a constructor that will be called if an exception is not thrown, and the selected constructor must be available, even if the call is canceled. - final note]

Effective Modern C++

RVO , RVO , copy elision, rvalue. , , , RVO , , std:: move

, , rvalue. , , 5, , . , std::move, , RVO ?

#include <iostream>
#include <string>


struct Test
{
    Test() {}

    Test(const Test& other)
    {
        std::cout << "Test(const Test&)" << std::endl;
    }

    Test(Test&& other)
    {
        std::cout << "Test(const Test&&)" << std::endl;
    }
};

Test foo(int param)
{
    Test test1;
    Test test2;
    return param > 5 ? std::move(test1) : test2;
}

int main()
{
    Test res = foo(2);
}

Test(const Test&).

+6
1

, RVO, operator ?. if, . foo :

Test foo(int param)
  {
  Test test1;
  Test test2;
  if (param > 5)
    return std::move(test2);
  else
    return test1;
  }

Test(Test&&).


, (param>5)?std::move(test1):test2:

, elision, , .

+5

All Articles