Почему имена функций классифицируются как выражения L-значений?

Согласно статье Кристофера Стрейчи « Разновидности языков программирования» , посвященной денотационной семантике, в любых языках программирования имена могут быть связаны с привязываемыми значениями, что представлено функциейenvironment: Id -> D, гдеIdявляются именами (также известными как идентификаторы) и обозначениями (также известными как привязываемые значения). Если в языке есть команда присваивания, назначаемое значение, обозначаемое именем, может изменяться внутри лексической области имени посредством присваивания, но местоположение, содержащее назначаемое значение, остается постоянным, поэтому, чтобы среда оставалась статичной , только местоположения считаются привязываемыми. значения (т. е. включает, но не включает), а динамическая часть, которая связывает местоположения с назначаемыми значениями, представлена ​​функциейstate: L -> V, гдеLявляются местоположениями (также известными как L-значения) и хранимыми значениями (также известными как R-значения, содержимое или назначаемые значения).

В C++ имена функций не могут быть присвоены, поэтому они не обозначают местоположение (т. е. значения функций).Fне включены вVно вD, то естьD = L + F + …):

      void f();  // binding
void g();  // binding

int main() {
    f = g;  // assignment fails
    return 0;
}

Выходclang++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out:

      main.cpp:5:7: error: non-object type 'void ()' is not assignable
    f = g;  // assignment fails
    ~ ^
1 error generated.

Тем не менее, согласно стандарту C++ , имена функций классифицируются как выражения L-значений (выделено жирным шрифтом):

  • glvalue это выражение, оценка которого определяет идентичность объекта или функции.
  • prvalue — это выражение, оценка которого инициализирует объект или вычисляет значение операнда оператора, как указано в контексте, в котором оно появляется, или выражение, имеющее тип cv . void.
  • Значение x — это значение gl, обозначающее объект , ресурсы которого можно использовать повторно (обычно потому, что срок его существования приближается к концу).
  • lvalue это glvalue, которое не является xvalue.
  • Значение r — это значение prvalue или значение x.

Почему?

1 ответ

Категории значений в C++ характеризуются двумя свойствами:

  • можно переместить из
  • имеет личность

Дело не в том, можно ли что-то назначить, хотя категория значения определяет, можно ли использовать оператор присваивания.

Примечание. Есть две смешанные категории: lvalues ​​и xvalues ​​— это glvalues, а prvalues ​​и xvalues ​​— это rvalues.

Функции «имеют идентичность» , что означает, что существует имя или что-то еще, что их обозначает. В данном случае это имя функции. Например, имяобозначает основную функцию, поэтому это должно быть выражение lvalue или xvalue (т. е. gvalue). Более того, функцию нельзя переместить, поэтому имеет смысл использовать только lvalue, а не xvalues.

Объединение слов «может быть назначено» в смысле C++ с этой системой — неверный способ думать об этом. Существуют и другие неназначаемые выражения lvalue, такие как строковые литералы или имена константных объектов:

  • является lvalue, но его нельзя присвоить
  • также является неназначаемым lvalue, если оно объявлено какconst int x

Фактическая связь между значениями lvalue и назначаемостью такова:

  • чтобы что-то можно было назначать, оно должно быть lvalue (перегрузки операторов могут смягчить это правило)
  • не каждое lvalue можно назначить

Это не противоречит тому, что говорил автор, потому что автор не говорил, что каждое L-значение должно быть изменяемым.


См. также: Что такое значения rvalue, lvalue, xvalue, glvalue и prvalues?

Другие вопросы по тегам