2015-12-07 5 views
2

Ниже фрагмент кода является Из блога Герба Саттера hereнеправильный вывод на векторное назначение?

г ++ выходов 10. MSVC также выводит 10. Выходные данные могут отличаться для разных компиляторов.

Я не понимаю, как изменяется переменная i. Может ли кто-нибудь объяснить мне, как получается выход 10, Is 10 действительно правильный выход?

#include <iostream> 
#include <vector> 
#include <string> 

int main() 
{  
    std::vector<int> v = { 0, 0 }; 
    int i = 0; 
    v[i++] = i++; 
    std::cout << v[0] << v[1] << std::endl; 
} 

ответ

-1

Это проблема порядка исполнения, и это не определено в связи с C++ 11:

5.17 Назначение и составные операторы присваивания

Оператор присваивания (=) и сложные операторы присваивания все группы справа налево. Все они требуют модифицируемого lvalue как их левого операнда и возвращают значение lvalue, относящееся к левому операнду. Результат во всех случаях является битовым полем, если левый операнд является битовым полем. В всех случаях назначение секвенировало после значения вычислению правых и левые операндов, и перед тем вычисления значения выражения в назначении.

Проще говоря, модификация левого аргумента упорядочивается после вычисления значения, но не побочных эффектов вычисления, с обеих сторон и перед возвратом ссылки на объект.

поэтому действия, которые будут приняты, будут

А. оценить левую сторону (возвращаемое значение выражения я ++ = 0)

Б. возвращают ссылку на объект (возвращение ссылки на объект выражения V [я ++])

C. Compute побочные эффекты для левой стороны т.е. i-> 1

Д. вычислить побочные эффекты для правой стороны т.е. i-> 2

Как видно из приведенного выше правила, неясно, является ли порядок ABCD , или если он должен быть ACBD, так как порядок вычисления побочных эффектов не определен, если это должно произойти сначала для левой или первой для правой стороны.

+0

Просто dv, но нет причин ... Может быть стратегия ?! – g24l

1

EDITED

Мы оставим обсуждение непредсказуемого поведения вне, и просто сосредоточиться на том, как ваша программа поступает на указанном выводе.

Прежде всего, позволяет констатировать факт:

  • я ++ увеличит значение I, но вернуть исходное значение, которое я провел перед тем, как увеличивается.

от What is the difference between ++i and i++?.

Теперь линия

v[i++] = i++; 

оценивает, в вашем случае, в порядке "LHS" -> "РИТ" -> Назначение:

  • LHS, v [я ++]: я увеличивается на 1, а i ++ возвращает 0 в v [i ++].
  • RHS, i ++: i теперь имеет значение 1, но увеличивается до 2, однако i ++ возврата RHS 1.
  • Назначение: Сверху присваивание приводит к: v [0] = 1 (после чего i значение 2).

Следовательно, печать v [0] и v [1] будет оцениваться в 1 (обновленное значение) и 0 (как инициализировано) соответственно.

+0

Очень красивый подход к простому объяснению того, что происходит в конкретном случае, я вернул свой dv! пальцы вверх. – g24l

+0

Спасибо! Я надеюсь, что два ваших спутника на вашем ответе также пересмотрят после вашего редактирования, я думаю, что это также важный ответ. – dfri

+0

хорошо, что они были права на dv в начале, на самом деле не было ясно, что было спрошено! – g24l