编译器为什么不会重新排列强烈异常安全代码的优化?

3

在Jon Kalb提供的强异常安全代码中解决Cargill Widget示例的情况下,是什么阻止编译器重新组织操作,从而使代码不再具有强异常安全性?

#include <algorithm> // std::swap

template< typename T1, typename T2 >
class Cargill_Widget
{
public:
    Cargill_Widget& operator=( Cargill_Widget const& r_other )
    {
        using std::swap;

        T1 temp_t1( r_other.m_t1 ); // may throw
        T2 temp_t2( r_other.m_t2 ); // may throw
        /* The strong exception-safety line */
        swap( m_t1, temp_t1 ); // no throw
        swap( m_t2, temp_t2 ); // no throw

        return *this;
    }

private:
    T1 m_t1;
    T2 m_t2;
};

这是“编译器不能改变可观察行为”规则吗?

参考资料:

2个回答

2
你自己说了:编译器不能做任何可能会修改可观察行为的操作,而且必须考虑可能出现的异常情况。潜在地,由于这一点,重排序限制可能对优化产生显著的负面影响。实际上,有两种情况需要考虑:编译器不知道被调用函数中发生了什么,因此无法跨越它们进行重排序;或者编译器确实有能力优化跨越翻译单元,这种情况下,它通常能够确定函数不会抛出异常(假设它不会),因此可以像忽略异常一样进行精确的重排序。如果抛出异常可能导致可观察行为发生变化,则不进行重排序。

1
任何优化都必须保留代码的可证明属性。否则,任何代码都可以被一个什么也不做且极速运行的程序所替代。异常的影响是可证明属性的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接