C++中函数返回的临时对象是否为const?为何仅能绑定const引用
#include <iostream> using namespace std; void f(const int& x) { } int g() { int x = 0; return x; } int main() { f(g()); }
移除形参const后编译失败对应的语法规则
这个现象符合C的引用绑定规则:非const左值引用不能绑定到右值,包括表达式生成的临时对象。g()是按值返回int的函数,调用g()时会生成一个匿名的临时int对象,这个对象属于右值范畴。如果把f的形参改成int& x(去掉const修饰),就属于非const左值引用绑定右值的非法写法,编译器会直接报错。
C设置这条限制的原因很简单:非const左值引用的设计语义是允许修改绑定的目标对象,但临时对象会在当前完整表达式执行结束后立刻销毁,就算允许你通过引用修改它,修改结果也没有任何渠道被后续代码访问,属于毫无意义的逻辑漏洞。而const左值引用是规则明确允许的例外:当const左值引用绑定到临时对象时,临时对象的生命周期会被延长到这个引用的作用域结束,不会提前销毁。
g()返回生成的临时对象是否为const类型
这个临时对象本身不是const类型。
这是个非常普遍的认知误区:不少人觉得这里不能绑定非const引用,是因为临时对象自带const属性,实际上二者没有任何关系。只要函数是按值返回非const类型,不管返回的是int这种内置类型,还是自定义类类型,生成的临时对象默认都是非const的:比如你直接写g() = 2这种看起来离谱的代码,语法上是完全合法的;如果g返回的是std::string这类类类型,你也可以直接在临时对象上调用它的非const成员函数(比如g().append("test"))。只有当函数显式声明返回const类型(比如写const int g())时,返回的临时对象才带有const属性。
非const右值不能绑定到非const左值引用,是C++语法层面的硬性规则,和对象本身是不是const没有关联。
内容的提问来源于stack exchange,提问作者ionescu radu

