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

C++异常对象作用域疑问:为何未出现预期的副本行为?

关于C++异常对象拷贝与类型转换的问题解答

咱们来逐个拆解你遇到的两个疑问:

疑问1:为什么只看到1次拷贝,而非预期的2次?

Aj的说法在无编译器优化的早期C++标准里是成立的,但现代编译器会通过**复制消除(Copy Elision)**优化掉一次冗余拷贝:

  1. 执行throw Some_error {1};时,首先会创建一个临时Some_error对象(对应输出里的Some_error(1))。
  2. 早期规则中,这个临时对象会先拷贝到专门的异常存储区域(第一次拷贝),再从该区域拷贝到catch块的参数e(第二次拷贝)。
  3. 但C++11及以后的标准允许编译器直接用临时对象初始化catch的参数,跳过中间的异常存储对象拷贝,所以你只看到一次拷贝构造的调用(Some_error(copy::1.1))。

如果想验证这个优化,可以给g++加上-fno-elide-constructors参数禁用复制消除,此时就能看到两次拷贝构造的输出。

疑问2:拷贝后的err_code是1.1,但get_code输出1?

这是类型转换截断导致的问题:

  • 你的err_code是float类型,拷贝构造后的值确实是1.1。
  • 但get_code()函数的返回类型是int,当float类型的1.1转换为int时,会被截断为整数部分1,所以最终输出就是1。

只需要把get_code()的返回类型改成float,就能看到预期的1.1输出:

float get_code() const { return err_code; }

补充:catch使用引用的情况

当你把catch改为catch(Some_error& e)时,catch参数直接引用异常对象,不会触发拷贝构造函数:

  • 没有拷贝输出,直接使用原始的异常对象(err_code为1)。
  • get_code()返回int类型的1,和预期完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:37:51