cppcheck 警告:访问转发变量

Posted

技术标签:

【中文标题】cppcheck 警告:访问转发变量【英文标题】:cppcheck warning: access of forwarded variable 【发布时间】:2021-08-25 13:25:03 【问题描述】:

关于以下代码

#include <utility>

template <int i = 0, class F, typename... ArgsType>
void g(F&& f, ArgsType&&... args)

  if constexpr (i < 1) 
    f(std::forward<ArgsType>(args)...);
    g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);
  

cppcheck --enable=all 的运行会给出以下警告:

Checking test.hpp ...
test.hpp:8:53: warning: Access of forwarded variable 'args'. [accessForwarded]
      g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);
                                                      ^
test.hpp:7:7: note: Calling std::forward(args)
      f(std::forward<ArgsType>(args)...);
        ^
test.hpp:8:53: note: Access of forwarded variable 'args'.
    g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);
                                                    ^

这个警告是什么意思,为什么会触发它?

【问题讨论】:

Forwarding the same value to two or more functions 【参考方案1】:

它警告您,您的代码在潜在移动后使用了变量。

std::vector<int> v1, 2, 3;
g([](auto v_)   , std::move(v));

我们通过移动将v 传递给函数(因此我们传递了一个右值引用给它)。当它将在调用f(std::forward&lt;ArgsType&gt;(args)...) 中转发时,参数v_ 将通过窃取v 的内部来初始化。之后再次使用它(通过引用)是不明智的,因为它被定义为处于“有效但未指定的状态”。在这种状态下使用它可能会导致微妙且难以检测的问题。

除非一个类型记录了在它们被移动后可以使用它的对象,我们唯一能做的真正有效的操作就是给它一个新的值。您的代码没有这样做。

【讨论】:

【参考方案2】:

当你这样做时

f(std::forward<ArgsType>(args)...);

您正在使用完美转发将所有args... 传递给f。这意味着如果args... 中的任何一个是右值,并且如果f 从该右值移动到函数参数或函数内的变量,那么args... 中的对象现在将处于从状态移动,意味着它的价值现在已经消失了。然后当你重用args...

g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);

您现在可以使用已移动其内容且不再可用于读取的对象。这就是您收到警告的原因。如果你想同时调用这两个函数,你不能使用完美转发。

【讨论】:

以上是关于cppcheck 警告:访问转发变量的主要内容,如果未能解决你的问题,请参考以下文章

无法识别来自命令行的 cppcheck

cppcheck警告:变量未在带有初始化初始化的构造函数中实例化

在声纳中使用 C++ 社区插件的问题。 Cppcheck 不起作用

CppCheck:变量“bla”未赋值

如何使用 stdint.h 的 int64_t 变量(cpcheck 认为它是有符号整数)防止 %"PRIi64" (%lld) 的 cppcheck (v1.72) 警告

为啥 cppcheck 工具找不到未初始化的变量?