Что именно является «побочным эффектом» в C ++? - PullRequest
30 голосов
/ 05 марта 2012

Это стандартный термин, который хорошо определен, или просто термин, придуманный разработчиками для объяснения концепции (... и что это за концепция)?Как я понимаю, это как-то связано со всеобщим точками последовательности , но я не уверен.

Я нашел одно определение здесь , но это не таксделать каждый оператор кода побочным эффектом?

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

Может кто-нибудь объяснить, что термин «побочный эффект» формально означает в C ++, и каково его значение?

Для справки,некоторые вопросы, говорящие о побочных эффектах:

  1. Свободен ли оператор запятой от побочного эффекта?
  2. Заставить компилятор не оптимизировать операторы без побочных эффектов
  3. Побочные эффекты при передаче объектов в функцию в C ++

Ответы [ 4 ]

17 голосов
/ 05 марта 2012

«Побочный эффект» определяется стандартом C ++ в [intro.execution] следующим образом:

Чтение объекта, обозначенного изменчивым значением glvalue (3.10), изменение объекта, вызов библиотеки IФункция / O или вызов функции, выполняющей любую из этих операций, являются побочными эффектами, которые являются изменениями в состоянии среды выполнения.

9 голосов
/ 05 марта 2012

Что такое «побочный эффект» в C ++? Это стандартный термин, который хорошо определен ...

c ++ 11 черновик - 1.9.12: доступ к объекту, обозначенному volatile glvalue (3.10), изменение объекта, вызов функции ввода-вывода библиотеки или вызов функции, выполняющей любую из этих операций, - все стороны эффекты, которые являются изменениями в состоянии среды выполнения. Оценка выражения (или подвыражения) в целом включает в себя как вычисления значений (включая определение идентичности объекта для оценки glvalue и выборку значения, ранее назначенного объекту для оценки prvalue), так и инициирование побочных эффектов. Когда возвращается вызов библиотечной функции ввода-вывода или оценивается доступ к энергозависимому объекту, побочный эффект считается завершенным, даже если некоторые внешние действия, подразумеваемые вызовом (например, сам ввод-вывод) или энергозависимым доступом возможно, еще не завершено.

Я нашел здесь одно определение, но разве это не делает каждое утверждение кода побочным эффектом?

Побочный эффект - это результат оператора, выражения, оператора или функции, который сохраняется даже после завершения оценки оператора, выражения, оператора или функции.

Может кто-нибудь объяснить, что термин «побочный эффект» формально означает в C ++, и каково его значение?

Значение заключается в том, что при оценке выражений они могут изменять состояние программы и / или выполнять ввод / вывод. В C ++ допускаются выражения в бесчисленных местах: присвоение переменных, if / else / while условия, for шаги настройки / проверки / изменения цикла, параметры функции и т. Д. .... Несколько примеров: ++x и strcat(buffer, "append this").

В программе на C ++ Стандарт предоставляет оптимизатору право генерировать код, представляющий программные операции, но требует, чтобы все операции, связанные с шагами перед точкой последовательности, появлялись перед любыми операциями, связанными с шагами после точки последовательности.

Причина, по которой программисты на C ++ склонны заботиться о точках последовательности и побочных эффектах, заключается в том, что точек последовательности не так много, как вы могли бы ожидать. Например: учитывая x = 1; f(++x, ++x);, вы можете ожидать вызова f(2, 3), но на самом деле это неопределенное поведение. Это поведение остается неопределенным, поэтому оптимизатор компилятора имеет больше свободы для организации операций с побочными эффектами для выполнения в максимально эффективном порядке - возможно, даже параллельно. Это также позволяет избежать обременения авторов компиляторов обнаружением таких условий.

1. У оператора запятой нет побочных эффектов?

Да - оператор запятой вводит точку последовательности: шаги слева должны быть выполнены до выполнения справа. Есть список точек последовательности в http://en.wikipedia.org/wiki/Sequence_point - вы должны прочитать это! (Если вам нужно спросить о побочных эффектах, будьте осторожны при интерпретации этого ответа - «оператор запятой» НЕ вызывается между аргументами функции, элементами инициализации массива и т. Д. Оператор запятой используется относительно редко и несколько неясен. если вы не уверены, что такое оператор запятой.)

2. Принудительный компилятор, чтобы не оптимизировать операторы без побочных эффектов

Полагаю, вы имеете в виду «побочные эффекты». Компиляторы не обязаны поддерживать любую такую ​​опцию. Какое поведение они проявят, если попробуют? - Стандарт не определяет, что они должны делать в таких ситуациях. Иногда большинство программистов могут разделить интуитивное ожидание, но в других случаях это действительно произвольно.

3. Побочные эффекты при передаче объектов в функцию в C ++

При вызове функции все параметры должны быть полностью оценены - и их побочные эффекты вызваны - до того, как произойдет вызов функции.НО, нет никаких ограничений на компилятор, связанных с оценкой определенных выражений параметров перед любым другим.Они могут перекрываться, параллельно и т. Д. Итак, в f(expr1, expr2) - некоторые этапы оценки expr2 могут выполняться раньше, чем что-либо из expr1, но expr1 все равно может завершиться первым - это undefined .

6 голосов
/ 05 марта 2012

Термин «побочный эффект» возникает из-за различия между императивными языками и чисто функциональными языками. Выражение C ++ может делать три вещи:

  1. вычислить результат (или вычислить «нет результата» в случае выражения void),
  2. вызвать исключение вместо оценки результата,
  3. в дополнение к 1 или 2, в противном случае измените состояние абстрактного компьютера, на котором программа номинально работает.

(3) - это побочные эффекты, «основным эффектом» является оценка результата выражения. Исключения - это немного неуклюжий особый случай, когда изменение потока управления меняет состояние абстрактной машины (изменяя текущую точку выполнения), но не является побочным эффектом. Конечно, код для создания, обработки и уничтожения исключения может иметь свои побочные эффекты.

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

Итак, int foo(int a, int b) { return a + b; } просто вычисляет возвращаемое значение, больше ничего не меняет. Поэтому он не имеет побочных эффектов, что иногда является интересным свойством функции, когда дело доходит до рассуждений о вашей программе (например, чтобы доказать, что она правильная, или компилятором, когда она оптимизирует). У int bar(int &a, int &b) { return ++a + b; } есть побочный эффект, так как изменение объекта вызывающей стороны a является дополнительным эффектом функции помимо простого вычисления возвращаемого значения. Это не будет разрешено на чистом функциональном языке.

Материал в вашей цитате о том, что «оценка завершена», относится к тому факту, что результатом выражения (или возвращаемого значения функции) может быть «временный объект», который уничтожается в конце полного выражение, в котором это происходит. Таким образом, создание временного не является «побочным эффектом» по определению: другие изменения.

0 голосов
/ 05 марта 2012

1.9.6

Наблюдаемое поведение абстрактной машины - это ее последовательность читает и записывает данные volatile и вызывает библиотечный ввод / вывод функции.

Побочным эффектом является все, что влияет на наблюдаемое поведение.

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

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