cppcheck 警告:访问转发变量
cppcheck warning: access of forwarded variable
关于下面的代码
#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)...);
}
}
a 运行 of 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)...);
^
这个警告是什么意思,为什么会触发?
当你这样做时
f(std::forward<ArgsType>(args)...);
您正在使用完美转发将所有 args...
传递给 f
。这意味着如果 args...
中的任何一个是右值,并且如果 f
从该右值移动到函数参数或函数内的变量,那么 args...
中的对象现在将是处于 moved from 状态,这意味着它的价值现在已经消失了。当你再使用 args...
g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);
您现在可以使用内容已被移动且不再可用于阅读的对象。这就是您收到警告的原因。如果要同时调用这两个函数,就不能使用完美转发了。
这是警告您,您的代码在潜在移动后使用了一个变量。
std::vector<int> v{1, 2, 3};
g([](auto v_) { }, std::move(v));
我们通过移动将 v
传递给函数(因此我们将右值引用传递给它)。当它将在调用 f(std::forward<ArgsType>(args)...)
中转发时,参数 v_
将通过窃取 v
的内部来初始化。在此之后再次使用它(通过引用)是不明智的,因为它被定义为处于“有效但未指定的状态”。在这种状态下使用它可能会导致微妙且难以检测的问题。
除非类型记录在对象被移出后可以使用它,否则我们能做的唯一真正有效的操作就是为它分配一个新值。您的代码不会那样做。
关于下面的代码
#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)...);
}
}
a 运行 of 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)...);
^
这个警告是什么意思,为什么会触发?
当你这样做时
f(std::forward<ArgsType>(args)...);
您正在使用完美转发将所有 args...
传递给 f
。这意味着如果 args...
中的任何一个是右值,并且如果 f
从该右值移动到函数参数或函数内的变量,那么 args...
中的对象现在将是处于 moved from 状态,这意味着它的价值现在已经消失了。当你再使用 args...
g<1>(std::forward<F>(f), std::forward<ArgsType>(args)...);
您现在可以使用内容已被移动且不再可用于阅读的对象。这就是您收到警告的原因。如果要同时调用这两个函数,就不能使用完美转发了。
这是警告您,您的代码在潜在移动后使用了一个变量。
std::vector<int> v{1, 2, 3};
g([](auto v_) { }, std::move(v));
我们通过移动将 v
传递给函数(因此我们将右值引用传递给它)。当它将在调用 f(std::forward<ArgsType>(args)...)
中转发时,参数 v_
将通过窃取 v
的内部来初始化。在此之后再次使用它(通过引用)是不明智的,因为它被定义为处于“有效但未指定的状态”。在这种状态下使用它可能会导致微妙且难以检测的问题。
除非类型记录在对象被移出后可以使用它,否则我们能做的唯一真正有效的操作就是为它分配一个新值。您的代码不会那样做。