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
    :标记可能未初始化使用的变量
在gcc(*)中,
-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; }());