考虑以下 mwe,实现一个重载乘法运算符的简单类:
#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;
}
Run Code Online (Sandbox Code Playgroud)
它编译并运行得很好,打印了预期的输出。但是 cppcheck 会给出以下警告。
tmp.cpp:15:48: error: Reference to temporary returned. [returnTempReference]
friend A &operator*(double b, A &m) { return m * b; }
Run Code Online (Sandbox Code Playgroud)
当重写(*)为
friend A &operator*(double b, A &m) { m * b; return m; }
Run Code Online (Sandbox Code Playgroud)
cppcheck 的错误消失。
那么,这是一个实际问题并且我正在监督某些事情,还是 cppcheck 误报?
一些上下文:在我的代码中,类A实际上是一个 Matrix 类,我不想在与常量相乘时创建一个新对象,从而返回引用。
您的代码不会返回对临时对象的引用。人们倾向于这样认为,因为您实现的operator*实际上是一个operator*=. 如果您确实实现了operator*不修改当前值A但返回新值的实现,那么返回引用将会出现问题。
我没有可用的工具,但我希望它不会抱怨:
#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;
}
Run Code Online (Sandbox Code Playgroud)
这实际上与您的代码相同,但具有*=.
正如 Songyuanyao 在评论中提到的那样,该工具可能只是期望m*b成为一个右值表达式,就像通常一样,而不实际检查*.