Overloading operators : const vs non-const return type : any difference of performance?

前端 未结 3 2017
余生分开走
余生分开走 2021-02-08 18:58

If we go to the wikipedia article about C++ operators, we have as an example :

Addition : a + b -> T T::operator +(const T& b) const;

S

相关标签:
3条回答
  • 2021-02-08 19:15

    Since you're returning a temporary rvalue instance of type T, this statement doesn't do anything unless there are some global side-effects in the assignment operation, such as modifications to static variables that are data members of the type T, output to a terminal, etc. Therefore depending on the type, and whether the assignment operator is a compiler default assignment operator, this entire operation may be safely elided in an optimization pass. If there is a user-defined assignment operator for type T, then the assignment operation won't be elided, but as mentioned before, unless there are global side-effects, this won't do anything past the life-time of the statement's execution since you are not storing the value of c in an object that resides in a named and accessible memory location.

    Keep in mind that if you do declare the return T type as const, and your operator method is not a const class method, you will disable certain types of operator chaining, as well as a host of other useful things, such as calling methods that have side-effects. For instance:

    (a+b).print(); //assuming print() is non-const method
    

    or assuming operator+ is not a const class method,

    d = (a+b) + c;
    
    0 讨论(0)
  • 2021-02-08 19:22

    This is an interesting question. In C++03, there would be no better chances to optimize with either of the two options and it would be a matter of style choice (I myself don't believe on the whole return by const to avoid unlikely errors).

    In C++11, on the other hand, it might actually have an impact. In particular, if your type supports move operations, and the copy/move out of the returned value cannot be elided, then by returning by const you are effectively disabling moves *

    // T is move assignable, with the usual declaration of a move assignment operator
    T f();
    const T g();
    int main() {
       T t;
       t = f();     // can move
       t = g();     // cannot move!!!
    }
    

    In your particular case, it depends on what large arrays means for you, if they are std::array (or otherwise arrays with automatic storage), then they cannot be moved, so this would not be an option anyway, but if the large arrays are dynamically allocated memory, moving will be much more efficient than copying. Note that in C++11 is the presence rather than the absence of const that can cause a performance penalty.


    * This is not 100% true, if the move assignment operator took the argument by rvalue-reference to const, then it could be moved. But none of the types in the standard library takes the argument this way, and I would not expect people to do it either (it would require const_cast inside the move operation (either constructor/assignment) and it just makes no sense: if you plan on moving (stealing) from it, why would you claim not to modify it??

    0 讨论(0)
  • 2021-02-08 19:25

    I would say don't ever implement operator + as member function. Just implement operator += which is definitely not const. Then you provide a global function which takes care about operator +, I think this is the most common way to do it.

    T& T::operator +=(const T& t)
    {
        // add t to object ...
        return *this;
    }
    
    T operator +(T t1, const T& t2)
    {
        t1 += t2
        return t1; // RVO will eliminate copy (or move constructor)
    }
    
    0 讨论(0)
提交回复
热议问题