Подтвердить что ты не робот

Что небезопасно?

Я увидел, что С++ 11 добавил ключевое слово noexcept. Но я не понимаю, почему это полезно.

Если функция выбрасывает, когда она не должна бросаться - почему я хочу, чтобы программа вышла из строя?

Итак, когда я должен использовать его?

Также, как он будет работать вместе с компиляцией с /Eha и с помощью _set_se_translator? Это означает, что любая строка кода может вызывать исключение С++, поскольку она может генерировать исключение SEH (из-за доступа к защищенной памяти), и оно будет переведено в исключение С++.

Что будет потом?

4b9b3361

Ответ 1

Основное использование noexcept относится к общим алгоритмам, например, при изменении размера a std::vector<T>: для эффективного движущегося элемента алгоритма необходимо заранее знать, что ни один из движений не будет бросать. Если движущиеся элементы могут выбрасываться, элементы необходимо скопировать вместо этого. Используя оператор noexcept(expr), реализация библиотеки может определить, может ли выполняться конкретная операция. Имущество операций, которые не бросаются, становится частью контракта: если этот контракт нарушен, все ставки отключены, и не может быть способа восстановить действительное состояние. Естественным выбором является спасение перед нанесением большего урона.

Для распространения знаний о noexcept операции не бросаются, необходимо также объявлять функции как таковые. Для этого вы должны использовать noexcept, throw() или noexcept(expr) с постоянным выражением. Форма, использующая выражение, необходима при реализации общей структуры данных: с выражением можно определить, может ли какая-либо из зависимых от типа операций генерировать исключение.

Например, std::swap() объявляется примерно так:

template <typename T>
void swap(T& o1, T& o2) noexcept(noexcept(T(std::move(o1)) &&
                        noexcept(o1 = std::move(o2)));

На основе noexcept(swap(a, b)) библиотека может затем выбирать по-разному эффективные реализации определенных операций: если она может просто swap() без риска исключения, она может временно нарушать инварианты и восстанавливать их позже. Если может быть выбрано исключение, библиотека может вместо этого скопировать объекты, а не перемещать их.

Маловероятно, что стандартная реализация библиотеки С++ будет зависеть от того, что многие операции будут noexcept(true). Вероятно, операции, которые он проверит, в основном связаны с движущимися объектами, то есть:

  • Деструктор класса (обратите внимание, что деструкторы по умолчанию noexcept(true) даже без какого-либо объявления, если у вас есть деструктор, который может быть брошен, вам нужно объявить его как таковое, например: T::~T() noexcept(false)).
  • Операторы перемещения, т.е. переместите конструкцию (T::T(T&&)) и переместите назначение (T::operator=(T&&)).
  • Операции типа swap() (swap(T&, T&) и, возможно, версия участника T::swap(T&)).

Если какая-либо из этих операций отклоняется от значения по умолчанию, вы должны объявить ее соответствующим образом, чтобы получить наиболее эффективную реализацию. Сгенерированные версии этих операций объявляют, бросают ли они исключения на основе соответствующих операций, используемых для членов и баз.

Хотя я могу представить, что некоторые операции могут быть добавлены в будущем или некоторыми конкретными библиотеками, я бы, вероятно, не стал бы выполнять операции объявления как noexcept. Если возникают другие функции, которые имеют значение noexcept, они могут быть объявлены (и могут быть изменены по мере необходимости) в будущем.

Ответ 2

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

Что касается MSVС++, вам нужно будет проверить, что происходит, когда они реализуют noexcept. С стандартной точки зрения SEH является undefined. Доступ к защищенной памяти уже может быть поврежден прямо сейчас.