Spring
Spring

Reputation: 900

Using of Operator Overloading form

I wonder in c++ about the operator overloading forms of the below like:

ClassName & operator+(ClassName &other)
ClassName operator+(ClassName &other)
Classname operator+(const ClassName &other)
Classname operator+(const Classname other)
Classname operator+(Classname other)

What are the difference of usage ??

Upvotes: 0

Views: 109

Answers (2)

Dietmar Kühl
Dietmar Kühl

Reputation: 153830

Just for reference: none of the quoted operators is the one normally actually overloaded! The one which is normally overloaded is more like this (assuming it is in the same namespace as ClassName):

ClassName operator+ (ClassName const& op1, ClassName const& op2) {
    ClassName rc(op1);
    rc += op2;
    return rc;
}

There are some variations how this operator can be implemented. In particular the first argument may be passed by value to avoid the copy in the implementation: in some cases the copy could be elided. This particular implementation using a named variable and returning it by name is intended to enable copy elision (as @juanchopanza pointed out, return ClassName(op1) += op2; isn't allowed to elide the copy for the return value).

With respect to your actual question, it is important to distinguish between references and values:

  • When a value like ClassName is used, the object being passed to a function or returned from a function is a copy. When the class in question is trivial, that is just OK but if the class is more complicated and allocates memory for its members there may be some cost in creating actual copies. On the other hand, semantically it is often necessary to use a copy. For example, the result of an addition is normally a different object and, thus, needs to be a copy.

    To take the edge out of the some of the costs, the compiler tries hard to avoid copies when it can. For example, when returning a local variable the copy is in many cases elided or the object is, at least, moved (assuming C++11 or later is used and the class has a move constructor).

  • When a reference like ClassName& or ClassName const& is used, the entity is actually just a name for an object. No copy is made but an object needs to exist somewhere. The presence of const vs. the absence of const just indicates whether all methods or only const methods can be called or whether a reference can be passed where another reference is needed: a non-const reference can be converted to a const reference but not vice verse.

    For the purpose of parameters, the key difference between const reference and non-const reference is that temporary objects cannot bind to non-const reference while they can bind to const references.

With that sorted, here is a run-through of the different declarations of the operator+():

  • ClassName & operator+(ClassName &other)

    This declaration takes a non-const reference as argument and returns a non-const reference. For the argument this means that it can't be a temporary but rather needs to have a name. For the return that means that the returned object needs to be kept alive. Normally the addition creates a new object and trying to keep an object alive is bound to not work. If ClassName is really expensive to copy you might not want to provide an operator+() but rather just an operatr+=() which semantically produces the same result as operator+() but does so in-place.

  • ClassName operator+(ClassName &other)

    This declaration has the primary constraint that the argument is a non-const reference, i.e., the argument cannot be a temporary object but has to be an lvalue, i.e., something which is somehow named. However, the arguemnt won't be copied.

  • ClassName operator+(const ClassName &other)

    This declaration works with temporaries and is one of the two likely candidates of how a member operator+() would look like. The argument still isn't copied but because it is [logically] immutable temporary objects can be used as arguments.

  • ClassName operator+(const ClassName other)

    This will copy the argument. For the purpose of the declaration the const will be meaningless and it can actually differ between different declarations of the same function. When the definition uses this declaration it means that the argument is copied, i.e., the operator+() has a local version but it can't actually change this copy. Most likely it will need to create another copy to produce a result. Correspondingly, I think defining a function with a const value argument is utterly pointless: if you want a constant, use const ClassName& or ClassName const& (these are identical; I do prefer the latter notation as it results in consistent placement).

  • ClassName operator+(ClassName other)

    Like the previous declaration this one copies the argument but the argument is mutable. Assuming the oepration is commutative, you can readily mutate other to produce the return value. Note, however, that copying other won't be elided (the compiler is not allowed to elide copying function parameters) but it can be moved. Assuming ClassName is either cheap to copy or other is used as the basis for the result, this is the other likely candidate how the operator is defined.

Upvotes: 3

MatthewRock
MatthewRock

Reputation: 1091

First one returns a reference, and takes a reference - this means that you can theoretically change both arguments, and you return a reference, which can be changed too. This is usually not what you want to do( 2 + 3 doesn't return 5 that can be reassigned to 17).

Second one is the same, but no reference returned.

Third has const reference - a reference which can't be modified. This is usually what you want to do, since you get element fast(you get the element), but you can't change it(incidentally or not).

Fourth one is like a third, but you copy an argument, and make it const for some reason. This makes little sense.

And the last one just takes a copy.

There isn't much difference between some of them - some of them make little sense if you think about what operator+ has to do; the area where they differ is mostly how you get the argument - and most of the time, you want to get it fast, so const ClassName& other is probably your best bet.

Upvotes: 1

Related Questions