Cppcheck 说“引用临时返回”,但代码运行良好。也许是误报?

LPr*_*Prc 4 c++ cppcheck

考虑以下 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 类,我不想在与常量相乘时创建一个新对象,从而返回引用。

for*_*818 6

您的代码不会返回对临时对象的引用。人们倾向于这样认为,因为您实现的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成为一个右值表达式,就像通常一样,而不实际检查*.

  • @SimhonH,这是一个误解,你可以像链接“*”一样链接“*=”。 (2认同)
  • @SimonH,大多数习惯使用惯用 c++ 的程序员预计 `a * b * c` 不会修改其任何操作数。你的“操作员*”违反了最小意外原则。其他使用你的“*”的人很可能会编写出损坏的代码,然后想知道为什么。另一方面,“operator*=”预计会完全按照您实现的方式执行 (2认同)