Можно ли использовать увеличенную переменную в колл-колле? - PullRequest
3 голосов
/ 11 июля 2019

Итак, я понимаю, что повторное использование переменной, которая была увеличена после публикации, является неопределенным поведением в вызове функции . Насколько я понимаю, это не проблема в конструкторах. Мой вопрос о tie, что странно на полпути между каждым.

Дано: pair<int, int> func() Могу ли я сделать:

tie(*it++, *it) = func();

Или это неопределенное поведение?

1 Ответ

3 голосов
/ 12 июля 2019

Начиная с C ++ 17, этот код имеет неопределенное поведение. Есть два возможных результата:

  • первый аргумент является результатом разыменования исходного итератора, второй аргумент является результатом разыменования инкрементного итератора; или

  • первый аргумент и второй аргумент являются результатом разыменования исходного итератора.

За [expr.call] / 8 :

[...] Инициализация параметра, включая каждый связанный вычисление значения и побочный эффект, неопределенно уважение к любому другому параметру. [...]

Таким образом, второй аргумент tie может быть результатом разыменования инкрементного итератора или исходного итератора.


До C ++ 17 ситуация была немного сложной:

  • , если и ++, и * вызывают функцию (например, когда тип it является сложным классом), то поведение было не указано , аналогично случаю начиная с C ++ 17;

  • в противном случае поведение было undefined .

По N4140 (черновик C ++ 14) [expr.call] / 8 :

[ Примечание: Оценки выражения постфикса и все аргументы не упорядочены относительно друг друга. Вся сторона Последствия оценки аргументов упорядочиваются до того, как функция введено (см. [intro.execution]). & Mdash; Конечная нота ]

Таким образом, код был неопределенным поведением, потому что оценка одного аргумента не была последовательной с другим. Оценка двух аргументов может совпадать, что приводит к гонке данных. Если не указано иное ...

По N4140 [intro.execution] / 15 :

При вызове функции (независимо от того, является ли функция встроенной), каждый вычисление значения и побочный эффект, связанный с любым аргументом выражение, или с постфиксным выражением, обозначающим вызываемый функция, последовательность перед выполнением каждого выражения или утверждение в теле вызываемой функции. [ Примечание: Значение вычисления и побочные эффекты, связанные с другим аргументом выражения не упорядочены. & Mdash; Конечная нота ] Каждая оценка в вызывающей функции (включая вызовы других функций), которая не в противном случае специально упорядочены до или после выполнения тело вызываемой функции неопределенно упорядочено относительно на выполнение вызываемой функции. 9 Несколько контексты в C ++ вызывают оценку вызова функции, даже если нет соответствующий синтаксис вызова функции появляется в блоке перевода. [ Пример: Оценка нового выражения вызывает одну или несколько функций выделения и конструктора; см. [expr.new]. Для другого Например, вызов функции преобразования ([class.conv.fct]) может возникают в тех случаях, когда синтаксис вызова функции не появляется. & Mdash; end example ] Ограничения последовательности при выполнении вызываемой функции (как описано выше) являются особенностями функции вызывает как оценивается, независимо от синтаксиса выражения, которое вызывает функция может быть.

9) Другими словами, выполнение функций не чередуется с каждым другой.

Таким образом, если операторы на самом деле являются вызовами функций, то поведение аналогично не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...