Учитывая строго безопасный для исключений код Джона Калба для решения примера 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;
};
Это «компилятор не может изменить наблюдаемое поведение«правило?
Ссылка:
Вы сами сказали: компилятор не может делать ничего, что
может изменить наблюдаемое поведение. И он обязан принять
возможные исключения во внимание. Потенциально, ограничения
на переупорядочение из-за этого может иметь значительный отрицательный
влияние на оптимизацию. Практически, есть два случая
Учтите: компилятор не знает, что происходит в
вызываемые функции, и поэтому не могут переупорядочивать их, или
у компилятора есть возможность оптимизировать
переводческие единицы, в этом случае, как правило, он сможет
определить, что функция не сгенерирует (при условии, что не сработает), и
таким образом, измените порядок, как если бы он игнорировал исключения. Или нет
изменить порядок, если создание исключения может привести к изменению
наблюдаемое поведение, если оно есть.
любая оптимизация должна сохранять доказуемые свойства кода. в противном случае любой код можно заменить программой, которая ничего не делает и работает максимально быстро. Эффекты исключений являются частью доказуемых свойств.