Что такое «побочный эффект» в 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 .