Что такое правило «как если бы»?

89

Как сказано в названии,

Что такое правило «как если бы»?

Типичный ответ, который можно получить:

Правило, разрешающее любые преобразования кода, которые не изменяют наблюдаемое поведение программы.

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

Примечание. Обозначьте это как C и C ++, потому что это относится к обоим языкам.

Алок Сохранить
источник
2
Это относится к абстрактной машине.
Алексей Фрунзе
« Пометить это как C и C ++, потому что это актуально для обоих языков » Это актуально для любого языка.
curiousguy
@AlexeyFrunze « Это относится к абстрактной машине » Это относится к состоянию «абстрактной машины», являющейся инструментом, а не целью, и не имеет отношения к согласованию, потому что это «абстрактный», который является инструментом спецификации, а не реальным.
curiousguy

Ответы:

98

Что такое правило « как если бы »?

Правило « как если бы » в основном определяет, какие преобразования разрешено выполнять реализации в законной программе на C ++. Короче говоря, все преобразования, которые не влияют на « наблюдаемое поведение » программы (точное определение см. Ниже), разрешены.

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


Где Стандарт вводит это правило?

Стандарт C ++ 11 вводит правило « как если бы » в параграфе 1.9 / 1:

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

Также в пояснительной сноске добавлено:

Это положение иногда называют правилом «как если бы» , потому что реализация может игнорировать любое требование этого международного стандарта, если результат такой, как если бы требование было выполнено, насколько это можно определить по наблюдаемому поведению. программы. Например, фактическая реализация не должна оценивать часть выражения, если она может сделать вывод, что его значение не используется и что никаких побочных эффектов, влияющих на наблюдаемое поведение программы, не возникает.


Что именно предписывает правило?

Пункт 1.9 / 5 дополнительно уточняет:

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

Стоит подчеркнуть, что это ограничение применяется только при «выполнении хорошо сформированной программы» , и что возможные результаты выполнения программы, которая содержит неопределенное поведение, не ограничены. Это также ясно указано в параграфе 1.9 / 4:

Некоторые другие операции описаны в этом международном стандарте как неопределенные (например, эффект попытки изменить константный объект). [Примечание: этот международный стандарт не налагает требований к поведению программ, которые содержат неопределенное поведение . - конец примечания]

Наконец, что касается определения " наблюдаемого поведения ", пункт 1.9 / 8 гласит следующее:

Наименьшие требования к соответствующей реализации:

- Доступ к изменчивым объектам оценивается строго по правилам абстрактной машины.

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

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

Все вместе они называются наблюдаемым поведением программы . [ Примечание : в каждой реализации может быть определено более строгое соответствие между абстрактной и фактической семантикой. - конец примечания ]


Есть ли ситуации, когда это правило не применяется?

Насколько мне известно, единственным исключением из правила « как если бы » является исключение копирования / перемещения, которое разрешено, даже если конструктор копирования, конструктор перемещения или деструктор класса имеют побочные эффекты. Точные условия для этого указаны в Пунктах 12.8 / 31:

При соблюдении определенных критериев реализации разрешается опускать конструкцию копирования / перемещения объекта класса, даже если конструктор, выбранный для операции копирования / перемещения, и / или деструктор для объекта имеют побочные эффекты . [...]

Энди Проул
источник
2
Я видел эту цитату. Что не ясно, так это определение наблюдаемого поведения. Что именно квалифицируется как наблюдаемое поведение? Copy elision, являющееся исключением из правила as-if, довольно хорошо известно и на самом деле не является частью моего вопроса.
Alok Save
2
@AlokSave: В стандарте C мы видим, что «доступ к изменчивому объекту, изменение объекта, изменение файла или вызов функции, которая выполняет любую из этих операций, являются побочными эффектами». Предположительно, в стандарте (ах) C ++ есть что-то эквивалентное. Неформально я предполагаю «все, что меняет его взаимодействие с внешним миром».
Оливер Чарльзуорт
1
Любое поведение, которое изменяет состояние абстрактной машины (то есть что-то, что изменяет переданную переменную или глобальную переменную, или читает и записывает на устройства ввода-вывода).
Матс Петерссон
1
Означает ли это, что разрешено удаление бесконечного цикла, который ничего не делает, если после этого не происходит ничего наблюдаемого?
Гарольд
5
Следует особо отметить, что это относится только к юридическим программам . Все, что вызывает неопределенное поведение , явно находится вне зоны действия.
vonbrand
15

В C11 правило никогда не называется этим именем. Однако C, как и C ++, определяет поведение в терминах абстрактной машины. Правило как если бы находится в C11 5.1.2.3p4 и p6 :

  1. В абстрактной машине все выражения оцениваются в соответствии с семантикой. Фактическая реализация не должна оценивать часть выражения, если она может сделать вывод, что ее значение не используется и что никаких побочных эффектов не возникает (включая любые, вызванные вызовом функции или доступом к изменчивому объекту).

  2. [...]

  3. Наименьшие требования к соответствующей реализации:

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

     

    Это наблюдаемое поведение программы.

Антти Хаапала
источник
-1

В C, C ++, Ada, Java, SML ... на любом языке программирования, хорошо определенном путем описания (обычно многих возможных, недетерминированных) поведения (й) программы (подверженной серии взаимодействий на портах ввода-вывода) , четкого правила «как если бы» не существует .

Примером особого правила является то, что деление на ноль вызывает исключение (Ada, Caml) или разыменование нуля вызывает исключение (Java). Вы можете изменить правило, указав что - то еще, и в итоге вы получите другой язык (который некоторые люди предпочли бы называть «диалектом» (*). Существует отдельное правило, чтобы указать некоторые различные варианты использования языка программирования, такие как отдельный грамматические правила охватывают некоторые синтаксические конструкции.

(*) Диалект, по мнению некоторых лингвистов, - это язык с «армией». в этом контексте это может означать язык программирования без комитета и конкретную отрасль редакторов компиляторов.

Правило «как если бы» не является отдельным правилом ; оно не распространяется на какую-либо конкретную программу и даже не является правилом, которое можно было бы обсуждать, удалять или изменять каким-либо образом : так называемое «правило» просто повторяет, что семантика программы определена и может быть только переносимой (универсально) определяется в терминах видимых взаимодействий выполнения программы с «внешним» миром.

Внешний мир может быть интерфейсами ввода-вывода (stdio), графическим интерфейсом пользователя, даже интерактивным интерпретатором, который выводит результирующее значение на чистом прикладном языке. В C и C ++ это включает (неопределенно определенный) доступ к изменчивым объектам, что является еще одним способом сказать, что некоторые объекты в данной точке должны быть представлены в памяти строго в соответствии с ABI (двоичный интерфейс приложения), без явного упоминания ABI.

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

Резюме:

  • Так называемое «правило как будто» не снимает ограничений на реализации.
  • Вы не можете удалить правило как если бы на любом языке программирования, указанном в терминах видимого поведения (трассировки выполнения, составленные для взаимодействия с внешним миром), чтобы получить отличный диалект.
  • Вы не можете добавить правило «как если бы» ни к одному языку программирования, не указанному в терминах видимого поведения.
любопытный парень
источник
Если люди считают, что я ошибаюсь, и существует четкое «правило как будто», почему бы им не попытаться описать вариант C ++ (диалект) без этого «правила»? Что могла бы означать спецификация C ++ без нее? Было бы абсолютно невозможно сказать, соответствует ли компилятор. Или даже дать определение соответствию.
curiousguy