Consider the following mwe, implementing a simple class that overloads the multiply operator:
#include <iostream>
using namespace std;
class A {
public:
double a;
A &operator*(double b)
{
a *= b;
return *this;
}
friend A &operator*(double b, A &m) { return m * b; } // (*)
};
int main()
{
A a;
a.a = 5.0;
a * 3.0;
std::cout << a.a << std::endl;
3.0 * a;
std::cout << a.a << std::endl;
return 0;
}
It compiles and runs just fine, printing the expected output. However cppcheck gives the following warning.
tmp.cpp:15:48: error: Reference to temporary returned. [returnTempReference]
friend A &operator*(double b, A &m) { return m * b; }
When rewriting (*) as
friend A &operator*(double b, A &m) { m * b; return m; }
The error from cppcheck disappears.
So, is this an actual problem and I'm overseeing something, or is it a false positive by cppcheck?
Some context: In my code, class A is actually a Matrix class, for which I don't want to create a new object upon multiplying with a constant, thus returning the reference.
Your code does not return a reference to a temporary. One is inclined to think that, because what you implemented as operator* is actually an operator*=. If you did implement operator* which does not modify the current A but returns a new one, then returning a reference would be problematic.
I don't have the tool available, but I would expect it to not complain about:
#include <iostream>
using namespace std;
class A {
public:
double a;
A &operator*=(double b)
{
a *= b;
return *this;
}
friend A &operator*=(double b, A &m) { return m *= b; } // (*)
};
int main()
{
A a;
a.a = 5.0;
a *= 3.0;
std::cout << a.a << std::endl;
3.0 *= a;
std::cout << a.a << std::endl;
return 0;
}
Which really does the same as your code, but with the expected semantics of *=.
As songyuanyao mentions in a comment, it might be that the tool simply expects m*b to be a rvalue-expression, as it usually is, without actually checking the implementation of your *.
It is a false positive on cppcheck side, but also your code is highly confusing to any readers (as shown in comments) because you don't obey basic rules and idioms for operator overloading. It may or not be related to cppcheck mistake.
Proper implementation of binary operator * should return a copy:
class A {
public:
double a;
// no need for friend declarations, your data member is public
};
A operator*(A a, double b)
{
A.a *= b;
return a;
}
A operator* (double b, A a)
{
return a * b;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With