В каком порядке происходит оценка постинкрементного оператора? - PullRequest
3 голосов
/ 29 марта 2010

С учетом

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 ]

11 голосов
/ 29 марта 2010

Первое - неопределенное поведение. Не указано, оценивается ли list[i] (для предоставления lvalue для lhs присвоения) до или после вызова функции objects.at.

Следовательно, существует законный порядок различных частей выражения, в котором к i обращаются (в list[i]) и изменяют отдельно (в i++) без промежуточной точки последовательности.

Это как раз условие неопределенного поведения в стандарте C ++ - существует ли такой законный порядок. Стандарт IIRC C выражает это немного по-другому, но с тем же эффектом.

Если сомневаетесь, не пишите выражение, которое использует оператор приращения, а также использует то же значение в любом другом месте выражения. Вы можете сделать это с помощью оператора запятой (i++, i++ хорошо) и условного оператора (i ? i++ : i-- хорошо), потому что в них есть точки последовательности, но это редко стоит. || и && также, и что-то вроде p != end_p && *(p++) = something; не совсем неправдоподобно. Любое другое использование, и если вы смотрите на него достаточно долго, вы обычно можете выработать порядок оценки, который все испортит.

Это кроме понимания сложных for выражений и for циклов с пустыми телами.

6 голосов
/ 29 марта 2010

Если сомневаетесь, предпочтите форму, которую легче понять (разверните цикл).

(И я думаю, list[i] = objects.at(i++) ведет к неопределенному поведению.)

1 голос
/ 29 марта 2010

Как уже было сказано, постинкрементная переменная в том же выражении, в котором она используется, дает неопределенное поведение.Однако, если вы хотите сохранить компактную форму, вы можете ввести точку последовательности и перейти к

for(unsigned int i = 0; i < objects.size(); list[i] = objects.at(i), i++);
1 голос
/ 29 марта 2010

Ссылка i в том же выражении, что и i++, вероятно, является неопределенным поведением. Но так как похоже, что вы используете контейнеры, не могли бы вы написать ...

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