为何C++中函数名被归类为L-value表达式?
为什么C++中函数名是L-value却无法赋值?
根据Christopher Strachey在指称语义学中的理论,编程语言里的名称会绑定到可绑定值,这可以用函数environment: Id -> D来表示——Id是标识符(名称),D是指称(可绑定值)。如果语言支持赋值,名称指代的可赋值值能在词法作用域内通过赋值改变,但存储值的位置是固定的。为了保持环境的静态性,只有位置会被当作可绑定值(也就是D包含位置类型L,但不包含存储值类型V),而关联位置和存储值的动态关系由state: L -> V表示,其中L是位置(即L-value),V是存储值(即R-value)。
在C++里,函数名不能被赋值,说明它们并不指代位置:函数值F不属于V,而是属于D(也就是D = L + F + …)。比如这段代码:
void f(); // 绑定函数名f void g(); // 绑定函数名g int main() { f = g; // 赋值操作失败 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++标准的定义,函数名属于lvalue表达式:
- glvalue:求值后能确定某个对象或函数标识的表达式。
- prvalue:用于初始化对象、计算操作数的值,或是类型为
cv void的表达式。- xvalue:一种glvalue,指代可复用资源的对象(通常是生命周期即将结束的对象)。
- lvalue:不是xvalue的glvalue。
- rvalue:prvalue或xvalue。
那为什么函数名不能赋值、不指代位置,却被归类为lvalue?
关键在于C++的lvalue定义和Strachey理论中的“位置(L-value)”不是完全等价的概念:
- C++中的glvalue核心是标识确定性——只要表达式能明确指向一个唯一的实体(不管是对象还是函数),它就是glvalue。函数有唯一的标识,所以函数名是glvalue。
- 而xvalue仅针对对象,函数不属于对象范畴,所以函数名不是xvalue,自然就被归类为lvalue。
- 赋值操作要求的是可修改的lvalue(modifiable lvalue),但函数名是不可修改的lvalue——C++不允许修改函数名的绑定关系,也不能给函数本身赋值,所以赋值操作会失败。
简单来说:C++的lvalue是“能确定标识的表达式”,而不是“可赋值的位置”,函数名满足前者但不满足后者,所以会出现这种看似矛盾的情况。
内容的提问来源于stack exchange,提问作者Géry Ogam
相关产品推荐
相关产品推荐

