C++ 如何绕过GCC‘*((无效*)&;b&x2B;4)和&x2019;在使用boost::optional时,此函数警告中可能未初始化使用
我有类似以下代码:C++ 如何绕过GCC‘*((无效*)&;b&x2B;4)和&x2019;在使用boost::optional时,此函数警告中可能未初始化使用,c++,boost,g++,boost-optional,C++,Boost,G++,Boost Optional,我有类似以下代码: #include <boost/optional.hpp> ::boost::optional<int> getitem(); int go(int nr) { boost::optional<int> a = getitem(); boost::optional<int> b; if (nr > 0) b = nr; if (a != b) return 1; return
#include <boost/optional.hpp>
::boost::optional<int> getitem();
int go(int nr)
{
boost::optional<int> a = getitem();
boost::optional<int> b;
if (nr > 0)
b = nr;
if (a != b)
return 1;
return 0;
}
#包括
::boost::可选的getitem();
内勤(内勤)
{
boost::可选a=getitem();
boost::可选b;
如果(nr>0)
b=nr;
如果(a!=b)
返回1;
返回0;
}
使用GCC 4.7.2和Boost 1.53编译时,请使用以下命令:
g++-c-O2-Wall-DNDEBUG
发出以下警告:
13:3:警告:“((void)&b+4)”可在未初始化的情况下在此函数中使用[-Wmaybe uninitialized]
显然,根本问题在于GCC。看见
有人知道解决方法吗?我发现将b的构造更改为以下(实际上相等)代码: 消除警告。但是,以下代码(实际上也是相等的):
boost::可选b(false,0);
不会消除警告。
这仍然有点不令人满意…gcc中有两个级别的未初始化分析:
:标记未初始化的变量-Wuninitialized
:标记可能未初始化使用的变量-Wmaybe uninitialized
-Wall
会同时启用两个级别,即使后者有虚假警告,因为分析不完善。虚假警告是一种瘟疫,因此避免它们的最简单方法是传递-Wno(可能未初始化)
(在-Wall
之后)
如果您仍然需要这些警告,但不希望它们导致生成失败(通过-Werror
),则可以使用-Wno error=可能未初始化的将它们列为白名单
(*)Clang不会激活-Wmaybe uninitialized
,默认情况下,这正是因为它非常不精确并且有大量误报;我希望gcc也遵循这条准则。对这段代码也有同样的问题:
void MyClass::func( bool repaint, bool cond )
{
boost::optional<int> old = m_sizeLimit; // m_sizeLimit is a boost::optional<int> class attribute
if ( cond )
m_sizeLimit = 60;
else
m_sizeLimit.reset();
if ( repaint )
{
if ( old != m_sizeLimit ) // warning here
doSomething();
}
}
我有一个不容易构造的类型,所以不想使用boost::make_可选路径。使用函数返回值分配自动变量对我来说解决了这个问题。因此,您可以:
boost::optional<Foo> Default()
{
return boost::none;
}
auto var(Default());
boost::可选默认值()
{
返回boost::无;
}
自动变量(默认值());
这也将作为一行lambda工作,因此您只需执行以下操作:
auto var([]()->boost::optional<Foo> { return boost::none; }());
autovar([]()->boost::optional{return boost::none;}());
auto b=boost::make_可选(false,0)代码>?@ RuNVB:使用AutoI,我认为这是更好的样式。我将更改答案。我收到了完全相同的警告,但此解决方案对我没有帮助。我必须完全去掉可选的
(幸运的是,在我的情况下,我可以这样做)。不知何故,这会导致gcc在这个变量上设置TREE\u NO\u警告内部标志。警告不太可能在未来的版本中出现,它比pragma更脆弱。你是一个救生员!:)奇怪的是,这只是GCC4.9.2的一个问题,它在4.9.3上运行得非常好。更重要的是,它在4.9.2的调试版本中运行良好,但在发布版本中失败。如果b
的构造函数没有初始化其中的所有内容,那么无论如何,b
在表达式a!=b
可能未初始化。如果您实际初始化b
?你还收到警告吗?@Shahbaz:b的构造函数在值不存在的地方创建了一个可选值。这是一个可选选项的有效行为。'a!=如果两个选项都未初始化,则b'应为真。所以这应该是有效的代码。使用值初始化“b”确实会消除警告,但这不是一个选项,因为它会更改代码的行为。“getitem()”返回的内容可能是未初始化的可选内容。感谢您提供的解决方案。遇到GCC4.9.2的问题,基于#pragma
的解决方案有效,是我的最佳选择。
boost::optional<int> old;
if ( m_sizeLimit )
old = boost::make_optional<int>(true, m_sizeLimit.value());
else
old = boost::make_optional<int>(false, 0);
#ifdef SDE_MOBILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
if ( old != m_sizeLimit ) // warning here
doSomething();
#ifdef SDE_MOBILE
#pragma GCC diagnostic pop
#endif
boost::optional<Foo> Default()
{
return boost::none;
}
auto var(Default());
auto var([]()->boost::optional<Foo> { return boost::none; }());