C++函数调用时直接创建临时对象传入引用形参为何不合法
原因解析
C++语法从规则层面就禁止非const左值引用(即你代码中定义的Bar &bar形参类型)绑定临时对象,这是刻意设计的防错机制,核心逻辑如下:
- 临时对象的生命周期非常短,你在函数调用语句里直接写
Bar(parameters)创建的匿名对象,会在当前这行表达式执行完成后立刻被销毁。如果允许非const引用绑定这类临时对象,函数内部对引用做的所有修改都会作用在即将销毁的对象上,修改结果完全无法留存,属于几乎没有业务价值、大概率是逻辑错误的写法,语法直接从编译阶段拦截这类问题。
举个典型的错误场景:void Foo(Bar& bar) { // 函数的设计意图是修改传入的bar对象,供调用者后续使用 bar.update_config(666); } // 如果语法允许传临时对象 Foo(Bar(init_args)); // 这行执行完临时Bar对象就销毁了,刚才的update_config修改完全没有留存,代码逻辑完全失效 - 从参数语义上看,函数使用非const左值引用作为形参,本身就隐含了契约:我会修改传入的实参,函数返回后你可以拿到修改后的结果。但临时对象是匿名的,调用方根本没有变量持有这个对象,就算函数完成了修改,调用方也没有途径访问修改后的结果,完全违背了这个形参的设计语义。
合法的写法参考
根据你的实际需求选对应写法即可:
- 如果函数不需要修改传入的对象,直接把形参加const修饰为
const Bar& bar即可。const左值引用允许绑定临时对象,还会自动把临时对象的生命周期延长到引用作用域结束,不会出现悬空问题。 - 如果函数确实需要修改传入的对象,就用你提到的第一种写法,先创建有名字的局部
Bar对象再传入,修改结果会保存在命名变量中,后续可以正常访问使用。 - C++11及之后版本支持的右值引用
Bar&&也可以绑定临时对象,但这是专门为移动语义设计的类型,和普通左值引用的适用场景完全不同,不要混用。
注:你给出的临时对象传参示例代码有笔误,
Foo(Bar(parameters);缺少右括号,正确写法应为Foo(Bar(parameters));
内容的提问来源于stack exchange,提问作者David Kendell
相关产品推荐
相关产品推荐

