Move Semantics and Pass-by-Rvalue-Reference in Overloaded Arithmetic

后端 未结 3 774
不思量自难忘°
不思量自难忘° 2021-02-13 21:01

I am coding a small numeric analysis library in C++. I have been trying to implement using the latest C++11 features including move semantics. I understand the discussion and to

3条回答
  •  独厮守ぢ
    2021-02-13 21:58

    I agree with David Rodríguez that it'd be a better design to use non-member operator+ functions, but I'll set that aside and focus on your question.

    I'm surprised that you see a performance degradation when writing

    T operator+(const T&)
    {
      T result(*this);
      return result;
    }
    

    instead of

    T operator+(const T&)
    {
      T result(*this);
      return std::move(result);
    }
    

    because in the former case, the compiler should be able to use RVO to construct result in the memory for the function's return value. In the latter case, the compiler would need to move result into the function's return value, hence incur the extra cost of the move.

    In general, the rules for this kind of thing are, assuming you have a function returning an object (i.e., not a reference):

    • If you're returning a local object or a by-value parameter, don't apply std::move to it. That permits the compiler to perform RVO, which is cheaper than a copy or a move.
    • If you're returning a parameter of type rvalue reference, apply std::move to it. That turns the parameter into an rvalue, hence permitting the compiler to move from it. If you just return the parameter, the compiler must perform a copy into the return value.
    • If you're returning a parameter that's a universal reference (i.e., a "&&" parameter of deduced type that could be an rvalue reference or an lvalue reference), apply std::forward to it. Without it, the compiler must perform a copy into the return value. With it, the compiler can perform a move if the reference is bound to an rvalue.

提交回复
热议问题