О перехвате исключений

Я пишу небольшую программу на С++ 11 и действительно использую исключения для одного из первых.

У меня вопрос о том, как эффективно поймать исключения, и после некоторых поисковых запросов у меня все еще нет ответа.

Вот вопрос: Чем эффективнее (или рекомендуется) между улавливанием исключения ссылкой (const?) Lvalue или ссылкой (const?) Rvalue?

В коде это дает:

1)

try { throw std::exception{"what"}; }
catch (std::exception& ex) {}

2)

try { throw std::exception{"what"}; }
catch (const std::exception& ex) {}

3)

try { throw std::exception{"what"}; }
catch (std::exception&& ex) {}

4)

try { throw std::exception{"what"}; }
catch (const std::exception&& ex) {}

Ответы

Ответ 1

Вы должны поймать ссылку const lvalue (2):

try { throw std::exception{"what"}; }
catch (const std::exception& ex) {}

Обоснование:

В С++ 11 возможно (с помощью shared_future), что два потока могут одновременно разматывать одно и то же исключение. Это может произойти в вашем коде, даже если вы не знаете о shared_future, если вы не управляете всем приложением.

Если два потока пойманы, разматывая одно и то же исключение одновременно, и один или оба потока изменяют исключение, тогда у вас есть условие гонки.

Итак, до тех пор, пока вам не нужно модифицировать объект исключения в предложении catch, пусть компилятор принудительно применяет эту политику для вас - catch by const&. Если вам действительно нужно изменить исключение, сделайте его копию, измените копию и выбросите копию. Вы можете сделать это, поймав по значению, если вы уверены, что это не будет срезать ваш объект исключения (что обычно не так, если вы ловите std::exception).

Ответ 2

Я полагаю, что это исключение должно быть принято обычным способом с помощью lvalue-reference. Вот хорошее объяснение использования rvalues-reference