C ++和数组索引中的前缀运算符奇怪

时间:2013-01-25 16:34:18

标签: c++ visual-studio-2010

所以我只是遇到了前缀运算符。

在Visual C ++ 2010中的调试版本中。

someArray[++index]

将正确递增数组索引,然后使用它来索引数组。

在我的发布版本中,它使用了数组索引,然后在之后增加了它,引起了一些巨大的麻烦。

奇怪的是我的调试构建代码实际上已经错了一段时间了,我把它写成

someArray[index++]

这将使用索引然后递增它,但是调试版本仍在递增它,然后使用该值。直到今天早上我才意识到我的错误。

以下是实际代码的示例。

for(unsigned int newPointIndex = 0; newPointIndex < newEdgeList.size() - 1;) {
    m_edges.push_back(Edge(newEdgeList[newPointIndex], newEdgeList[++newPointIndex]));
}

for循环中没有发生递增。当我索引到数组中时,它发生在循环内部的实际代码中。我认为这是一个聪明的小优化,但它使它在发布版本中无法正常工作。

我第二次索引到数组时,它在发布版本中使用了未增加的索引,但是在调试版本中工作。

2 个答案:

答案 0 :(得分:6)

你的for循环体包括:

Edge(newEdgeList[newPointIndex], newEdgeList[++newPointIndex])

那是 undefined 未指定的 undefined [1]行为,因为这两个参数可以按任意顺序(甚至同时)进行评估,所以不清楚是否{{1在第一次使用之前,它们会增加或不增加。

调试和优化的构建非常有可能以不同的顺序评估参数。

我建议将newPointIndex增量放在for语句本身,然后写入正文:

newPointIndex

[1]:阅读关于un {specified,defined}讨论的评论。 tl;博士:神圣的飞跃蜥蜴,蝙蝠侠!

答案 1 :(得分:5)

问题实际上就在这里:

m_edges.push_back(Edge(newEdgeList[newPointIndex], newEdgeList[++newPointIndex]));

您无法分辨首先执行两个表达式newEdgeList[newPointIndex]newEdgeList[++newPointIndex]中的哪一个。

根据C ++标准,无保证它们将从左到右执行。见5.2.2 / 8:

“后缀表达式和参数表达式的评估都是未经过排序 相对于彼此。在输入函数“

之前,对参数表达式评估的所有副作用进行排序

同样相关的是1.9 / 15:

“当调用函数时(无论函数是否为内联函数),在执行每个表达式之前,对与任何参数表达式或指定被调用函数的后缀表达式相关联的每个值计算和副作用进行排序或者在被调用函数体中的语句。[注意:与不同参数表达式相关的值计算和副作用是未被排序的。-end note]“

这意味着一个实现是免费的不仅在调试中具有不同的执行顺序以释放构建,但理论上也是每次执行该语句时都改变顺序在相同的程序执行中,并且没有确定的方式

解决方案包括从这些子表达式中取出增量(如另一个答案所述)。