后增量算子的评估会以什么顺序发生?

时间:2010-03-29 14:20:00

标签: c++ stl operator-precedence

鉴于

std::vector<CMyClass> objects;
CMyClass list[MAX_OBJECT_COUNT];

这样做是明智的吗?

for(unsigned int i = 0; i < objects.size(); list[i] = objects.at(i++));

或者我应该将循环扩展到此?

for(unsigned int i = 0; i < objects.size(); i++)
{
  list[i] = objects.at(i);
}

4 个答案:

答案 0 :(得分:11)

前者是未定义的行为。在函数调用list[i]之前或之后,未指定是否评估objects.at(为赋值的lhs提供左值)。

因此,表达式的各个部分都有一个合法的排序,其中i被访问(在list[i]中)并被单独修改(在i++中),没有插入序列点。

这正是C ++标准中未定义行为的条件 - 是否存在这样的合法排序。 IIRC的C标准表达方式略有不同,但效果相同。

如果有疑问,请不要编写使用增量运算符的表达式,并在表达式的其他位置使用相同的值。您可以使用逗号运算符(i++, i++很好)和条件运算符(i ? i++ : i--很好),因为它们中有序列点,但它很少值得。同样地||&&p != end_p && *(p++) = something;之类的东西并非完全不可信。任何其他用途,如果你盯着它足够长的时间,你通常可以制定一个评估令,这会使事情变得混乱。

除了复杂的for表达式和for循环与空体的可理解性之外。

答案 1 :(得分:6)

如果有疑问,请选择更容易理解的形式(扩展循环)。

(我认为list[i] = objects.at(i++)导致未定义的行为。)

答案 2 :(得分:1)

在与i相同的表达式中引用i++可能是未定义的行为。但既然看起来你正在使用容器,你可以写一下......

list = objects;                               // if they're the same type
list.assign(objects.begin(), objects.end());  // if not

答案 3 :(得分:1)

正如已经说过的那样,在使用的同一表达式中对变量进行后递增会产生未定义的行为。 但是,如果您希望保留紧凑形式,可以引入序列点并转到

for(unsigned int i = 0; i < objects.size(); list[i] = objects.at(i), i++);