前增量算子的奇怪警告

时间:2014-05-23 09:17:53

标签: c++

我实施了一个"增量平均值" (我只是伪装成.cpp文件)

#include "../hpp/CIncrementalMean.hpp"

IncrementalMean::IncrementalMean() : m_mean(0.0), m_cntr(0) {}

IncrementalMean::~IncrementalMean() {}

void IncrementalMean::addValueToMean(double valIn)
{
  m_mean = (m_cntr * m_mean + valIn) / ++m_cntr;
}

int IncrementalMean::getCounter() const
{
  return m_cntr;
}

double IncrementalMean::getMean() const
{
  return m_mean;
}

当我构建它(gcc4.9 Ubuntu14.04)时,我收到以下警告:

warning: operation on ‘((IncrementalMean*)this)->IncrementalMean::m_cntr’ may be undefined [-Wsequence-point]

我不确定为什么显示它。有人可以给我一个建议吗?我要做什么

m_mean = (m_cntr * m_mean + valIn) / (m_cntr + 1);
m_cntr++;

代替?

但无论如何,有人可以向我解释警告吗?

3 个答案:

答案 0 :(得分:4)

m_mean = (m_cntr * m_mean + valIn) / ++m_cntr;
        ^^^^^^^^^                   ^^^^^^^^^^
         READING                     WRITING

您正在读取和编写操作之间没有sequence point的变量。这可以由编译器重新排列,因此它是Undefined Behaviour:D

修改: 补充一点,如果你使用:

,你将有更少的浮点误差累积
m_mean += (valIn - m_mean) / ++m_cntr;

(请参阅here AND 您将避免未定义的行为。

答案 1 :(得分:3)

让我们简化您的代码以确定问题:

a = 0;
b = a / ++a;

在第2行完全执行了什么划分?你可能认为它一定是:

b = 0 / 1;

事实上,编译器可以先评估++a,然后a秒,给你:

b = 1 / 1;

那么代码是做什么的?技术术语是"未定义的行为",但您需要记住的是不要增加变量并在同一个表达式中再次使用#34;。

关于您的设计,拥有两个数据成员countersum可能更有意义,并将该部门推迟到名为calculateMean的成员函数。然后,每次调用addValue时,你都不必繁殖和分裂(我闻到精确问题!)。

答案 2 :(得分:2)

自4.6.3以来GNU编译器集合(GCC)在操作的顺序顺序不明确时发出警告。

由于您在分母中修改m_cntr并在分子计算中使用此值,因此不明确将要做什么(即,此分数的哪一部分将在先前计算)。因此,最好避免这种结构。