Почему имена функций классифицируются как выражения 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.
Функции «имеют идентичность» , что означает, что существует имя или что-то еще, что их обозначает. В данном случае это имя функции. Например, имя
Объединение слов «может быть назначено» в смысле C++ с этой системой — неверный способ думать об этом. Существуют и другие неназначаемые выражения lvalue, такие как строковые литералы или имена константных объектов:
-
является lvalue, но его нельзя присвоить -
также является неназначаемым lvalue, если оно объявлено как const int x
Фактическая связь между значениями lvalue и назначаемостью такова:
- чтобы что-то можно было назначать, оно должно быть lvalue (перегрузки операторов могут смягчить это правило)
- не каждое lvalue можно назначить
Это не противоречит тому, что говорил автор, потому что автор не говорил, что каждое L-значение должно быть изменяемым.
См. также: Что такое значения rvalue, lvalue, xvalue, glvalue и prvalues?