为什么在按值捕获异常时将异常对象移动到 catch-clause 对象而不被标准化,以防它没有被省略?

Why is it not standardized that an exception object is moved to a catch-clause object when catching the exception by value in case it is not elided?

在抛出表达式中,如果编译器无法执行复制省略但满足或将满足复制省略的条件,除了源是函数参数,编译器将尝试使用移动构造函数,即使该对象由左值指定;

在catch子句中,以下是允许的:当参数与抛出的异常对象的类型相同(忽略cv限定)时,异常对象的副本被省略并且catch子句的主体直接访问异常对象,就像通过引用捕获一样。如果这种复制省略会出于任何原因改变程序的可观察行为而不是跳过 catch 子句参数的复制构造函数和析构函数(例如,如果 catch 子句参数被修改,并且异常对象被重新抛出)与投掷)。

在我看来,如果满足此复制省略的条件,执行移动到 catch 子句参数是一个合理的解决方案,但编译器无法执行。

由于它仅针对复制省略是安全的情况,因此它也是完全安全的(例如,不会阻止重新抛出异常的最佳实现)。

为什么不是这样?

与任何其他功能一样,throw 表达式中的复制省略需要先实现。

移动自身(不考虑例外情况)是该语言的必备功能,不支持此功能的代价是不可原谅的。

应用这个已经存在的特性,在抛出表达式中以指定的方式移动比实现复制省略要容易得多。

指定的条件对于移动来说是很自然的,编译器工程师和编译器在 运行 时间内执行它并没有太多额外的工作。

但是在那里实现复制省略需要工程师进行更多的额外工作,并且使编译算法更加复杂。

因此,在某些或所有情况下不支持某些复制省略的成本允许编译器更简单。


在 catch 子句中,复制省略的唯一困难是满足条件,复制省略本身在那里很容易实现。复制省略和移动到那里的条件仍然相同,实施难度也大致相同。

但是复制省略显然比移动更有效率

所以没有理由让编译器工程师和编译器加载移动功能。