Что такое "побочный эффект" на С++?

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

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

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

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

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

Ответ 1

A "побочный эффект" определяется стандартом С++ в [intro.execution], посредством:

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

Ответ 2

Что такое "побочный эффект" на С++? Является ли это стандартным термином, который хорошо определен...

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

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

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

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

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

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

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

1. Является ли запятый оператор свободным от побочного эффекта?

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

2.Force компилятор для оптимизации без побочных эффектов

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

Эффекты 3.Side при передаче объектов в С++

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

Ответ 3

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

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

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

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

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

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

Ответ 4

1.9.6

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

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

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