Visual Studio 2010 - 前缀运算符 C++和数组索引中的奇怪性
visual studio 2010 - Prefix Operator Strangeness in C++ and array indices
所以我在前缀运算符上遇到了一个巨大的头痛。
在 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 循环中没有发生递增。 它发生在我索引到数组时循环内的实际代码中。 我认为这是一个聪明的小优化,但它使它在发布版本中不起作用。
我第二次索引到数组中时,它在发布版本中使用未递增的索引,但在调试版本中工作。
你的 for 循环体包括:
Edge(newEdgeList[newPointIndex], newEdgeList[++newPointIndex])
这是未定义的未指定未定义 [1] 行为,因为这两个参数可以按任一顺序(甚至同时)计算,因此不清楚newPointIndex
在第一次使用之前是否会增加。
调试和优化版本很可能以不同的顺序评估参数。
我建议将newPointIndex
增量放在 for 语句本身中,并写在正文中:
Edge(newEdgeList[newPointIndex], newEdgeList[newPointIndex + 1])
[1]:阅读讨论未{指定,已定义}的评论。 博士:神圣的跳跃蜥蜴,蝙蝠侠!
问题实际上就在这里:
m_edges.push_back(Edge(newEdgeList[newPointIndex], newEdgeList[++newPointIndex]));
您无法判断两个表达式中的哪一个newEdgeList[newPointIndex]
,newEdgeList[++newPointIndex]
将首先执行。
根据C++标准,不能保证它们会从左到右执行。参见 5.2.2/8:
"后缀表达式和参数表达式的计算都是未排序的彼此相对。参数表达式计算的所有副作用在输入函数之前都已排序"
同样相关的是 1.9/15:
"当调用一个函数(无论该函数是否是内联的)时,与任何参数表达式或指定被调用函数的后缀表达式相关的每个值计算和副作用都是在执行被调用函数主体中的每个表达式或语句之前排序的。[注意:与不同参数表达式相关的值计算和副作用是未排序的。
这意味着实现不仅可以在调试发布构建中对这两个表达式具有不同的执行顺序,而且理论上还可以在每次在同一程序执行中执行该语句时更改顺序,并且没有确定性的方式。
解决方案包括从这些子表达式中取出增量(如另一个答案所示)。
- 特征获取索引数组,其中向量中的值为真(不需要循环)
- 是否可以使用字符串或字符索引数组
- 为什么在使用字符索引数组时会出现这种不同的行为
- 在具有重复索引的索引数组处更改 ArrayFire 数组
- 使用索引数组订购 ArrayFire Array 的最佳方式
- C++ 中结构的动态索引数组
- 1索引数组上的qsort()正在扰乱索引
- C++ 索引数组打印和删除字符串名称 数组打印
- 字符串下标超出范围.我不知道如何使用字符索引数组,所以我使用了(无符号整数),但它不起作用
- openGL drawElements - 一个额外的三角形,使用索引数组
- 具有索引数组的地形(高度贴图)LOD
- 通过创建索引数组进行 C++ 排序
- OpenGL:两个顶点数组 + 两个索引数组
- 将索引数组排序为主数组
- 自动循环跳过某些索引数组
- 为静态强制转换的索引数组生成数组
- 重载枚举索引数组的std::get
- 使用c++中的第二个索引数组对数组进行排序
- 给定的零索引数组 &该数组的均衡索引
- CUDA:重新索引数组