I have a class A
with move constructor, assignment operator, copy constructor, assignment operator.
The class uses (non-friend, non-member)
template <typename T>
const A<T> operator*(A<T> lhs, const A<T>& rhs)
{
lhs *= rhs;
return lhs;
}
and
template <typename T>
A<T>& A<T>::operator*=(const A<T>& rhs)
{
// assert sizes are the same
// This is essentially a std::vector<T> wrapper
for (each variable) {
variable *= rhs.variable;
}
return *this;
}
If in my main()
function, I call:
obj1 = (obj2 * obj3);
, then the log outputs (some names might be wrong due to poor labelling within the copy constructor etc):
obj2 copy-constructed
obj2 move-constructed
obj1 copy-assigned from obj2
whereas for obj1 = obj2; obj1 *= obj3;
I get:
obj1 copy-assigned from obj2
Seemingly the multiplication operators will be called the same either way.
Is the second implementation really so different? (Crucially, this is better, right?) Some reading around makes it seem logical that these things are all called as they are - I'm just curious if I can skip a lot of calls by splitting the multiplication to two statements, etc.
Also
: The non-friend, non-member operator*(..) takes the first argument by value, and then doesn't need to create a temporary object. This is still using the copy-constructor (to construct the argument), but this link (pass-by-value-or-const-reference) makes it seem likely I can't do worse by defining it this way. Is that right?