This post is part of a series of tutorials on C++
Unlike the previous post on arithmetic operators, there is a more canonical form you might want to follow. While it is considered best practice for C++, it can sometimes encounter performance penalities because of the pass-by-copy and return-by-copy approach (I found this version slowed down my ray tracer significantly).
The idea relies on a couple of principles:
If you code a given operator
#, then you should code
#=. For example, if you code
operator+()then you should code
operator+=(). This is almost always a good idea and you should do this anyway (it’s rule 3 of the c++ - Three Basic Rules of Operator Overloading (stackoverflow.com).
But, if you bother to code one version, you might want to take advantage of code reuse (not always the best choice, but it does help prevent code bugs).
Taken together, this forms the following canonical form:
This is kind of a neat way to code things up. You only have to implement addition once (in the compound
operator+=(). You then can use the
friend function to define the binary arithmetic
operator+(). In this case, the
friend function is both declare and defined within the class, with allows the compiler to do some optimizations (the function is automatically inlined).
But, you can pay a penalty here if you’re not carefuly. The problem is that
lhs is passed-by-value, which calls a copy constructor once. And after the
+=, you then return another copy of
lhs by value, creating another copy call. This can be suboptimal if you have no created the right assignment operators to handle this gracefully. In particular, this requires a properly coded move assignment (cppreference.com), which can be a handy thing to have if you class has no dynamically allocated heap memory. You may also find my discussion on Assignment Operators, Part 2 to be interesting to consider in this context.
Still, for the most basic use cases, the important takeaway is that if you’re going to code a binary arithmetic operator, you should also code the compound one. And, if you can reuse code between the two, try to!