Ответ 1
За исключением деструкторов, функций подкачки, конструкторов перемещения и операторов присваивания перемещения, стандарт помечает функцию как noexcept
только если она имеет широкий контракт, т.е. Не имеет предварительных условий. Эта перегрузка требует, чтобы аргумент был строкой с нулевым символом в конце, поэтому стандарт не помечает его как noexcept
.
Рациональное указано в N3248:
Функции, отмеченные как
noexcept
, трудно проверитьКогда функция помечена как
noexcept
становится невозможным пометить тестовые сбои, особенно в тестовых драйверах, с помощью исключения. Типичным примером может служить код, который проверяет предварительные условия при входе в функцию:T& std::vector<T>::front() noexcept { assert(!this->empty()); return *this->data(); }
При проверке таких защитных проверок тестовым драйвером разумным подходом является регистрация обработчика утверждений, который выдает четко определенное исключение, нарушенное предварительным условием, которое тестовый драйвер перехватывает, чтобы убедиться, что соответствующее
assert
действительно существует....
Теперь мы можем утверждать, что вызов функции вне контракта, когда
vector
пуст, является неопределенным поведением, поэтому мы не должны ожидать никаких гарантий. Проблема в том, что неопределенное поведение задается библиотекой; для компилятора этот код прекрасно определен, и, еслиassert
выдает исключение, программа должна завершиться точно определенным образом, нарушая работу тестового драйвера.Обратите внимание, что проблема здесь не в том, что мы используем утверждения для поиска ошибок в наших собственных реализациях библиотеки, а скорее в пользовательском коде, который неправильно вызывает нашу библиотеку. Если мы уберем возможность проверять эти защитные утверждения, мы можем ошибиться и таким образом подвергнуть наших пользователей риску совершения гораздо более серьезных ошибок, чем распространение неожиданного исключения.