You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何std::runtime_error的构造函数接受std::string的const引用?

关于std::runtime_error构造函数参数传递的疑问解答

嘿,这个问题问到点子上了!先明确一下,你说的这个构造函数签名确实是std::runtime_error(const std::string& what_arg);,而且你的推测完全没错——新构造的异常对象必然会持有传入的std::string的副本,毕竟异常要在栈展开后还能正常访问错误信息,总不能依赖外部可能已经被销毁的字符串对吧?那为啥要用const引用而非值传递呢?核心原因就俩字:性能。

具体来说,分这几点讲:

  • 避免额外的拷贝开销:如果用值传递,不管你传入的是一个左值(比如已经存在的std::string变量)还是临时对象,都会先触发一次拷贝构造,把实参复制到函数的形参里;然后异常对象内部再做一次拷贝,把形参的内容复制到自己的成员变量里。等于平白多了一次完全没必要的拷贝。而用const引用的话,形参只是绑定到实参上,异常对象只需要做一次拷贝就够了,对于长字符串来说,这个性能差异会很明显。
  • 完美兼容临时对象:const引用可以安全地绑定到临时对象上(比如throw std::runtime_error("Oh no, something broke!");里,字符串字面量会被隐式转换成临时std::string),既不会有额外拷贝,又能保证临时对象的生命周期足够完成异常对象的构造。
  • 兼容旧代码与左值场景:虽然C11之后新增了移动语义的构造函数std::runtime_error(std::string&& what_arg);,可以把临时对象的资源直接“偷”过来(零拷贝),但const引用版本依然不可或缺——对于已经存在的左值字符串,用const引用传递再拷贝,还是比传值少一次拷贝,而且能兼容所有C版本的代码。

总结一下:你猜的“异常对象必须持有副本”是对的,用const引用传递参数,是为了在保证能拿到实参内容的前提下,避免传值带来的额外拷贝开销,兼顾性能和兼容性。

内容的提问来源于stack exchange,提问作者plats1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:38:40