Если теоретически, но не практически, функция бросания будет объявлена noexcept?
Можно ли объявить следующую функцию noexcept
, хотя v.at(idx)
теоретически может генерировать исключение out_of_range
, но практически не из-за проверки границ?
int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept {
if (idx >= v.size()) {
return -1;
}
return v.at(idx);
}
Ответы
Ответ 1
Что вы называете "безопасным"? Если вы выбрали исключение в функции, помеченной как noexcept
или noexcept(true)
, то ваша программа будет прекращена (стандарт 15.4.9)
Всякий раз, когда генерируется исключение, и поиск обработчика (15.3) встречается с внешним блоком функция с спецификацией исключения, которая не позволяет исключение, затем
- Если спецификация исключений является спецификацией dynamic-exception, функция std:: неожиданна() (15.5.2),
- в противном случае вызывается функция std:: terminate() (15.5.1).
Пока это приемлемо, тогда вы в порядке. Если вы не можете терпеть завершение программы, это небезопасно.
Ответ 2
Это безопасно. Объявление функции noexcept
приведет к немедленному завершению программы (вызовом terminate()
), если возникает исключение. Пока не исключено исключение, все в порядке.
Ответ 3
У нас нет полного сценария, чтобы точно определить, сможет ли эта функция бросить.
Ваши предположения хотя и правильны: поскольку вы делаете то, что std::vector::at
в любом случае будет делать, это вряд ли будет вредным в данном контексте. Однако, как правило, такая функция может быть подвержена недействительным факторам и, таким образом, потенциально может генерировать исключение. Это могут быть потоки, процессы или сигналы, которые могут чередовать исполнение в код, который может изменить std::vector
, который не может безопасно справиться с этим, и не может std::vector::at
.
Если вы хотите рассмотреть эти возможности, вам нужно иметь что-то вроде
int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept
{
try { return v.at(idx); }
catch (std::out_of_range const& e) { return -1; }
}
Ответ 4
хотя v.at(idx)
теоретически может генерировать исключение out_of_range
, но практически не из-за проверки границ?
Теоретически он не мог.
Если вы теоретически думаете об этой функции, то проверка границ является частью того, что вы должны учитывать в теории этой функции в целом, и поэтому единственным теоретическим способом, который она могла бы сделать, является наличие в который idx >= v.size()
не был истинным, и все же v.at(idx)
бросил.
Таким образом, в вашем заявлении, что он "теоретически может бросить", неверно.
(На практике это может быть брошено, если у вас была ошибка при использовании at()
в использовании, но тогда у вас есть большие проблемы и взорвать, поскольку noexcept
может заставить вас сделать, вероятно, к лучшему).
Ответ 5
Возможно, кто-то из крупной организации O сделал умный и вывел свой класс из std::vector<int>
, а затем перегрузил как size(), так и at(), чтобы бросить по своему вкусу. Затем где-то в коде вызывается ваша функция, но для всех удивление программа завершается, а исключение оказывается выше.
На самом деле далека, но это не вопрос только о std::vector<int>
..., а о практике программирования.
К сожалению, вы предполагаете, что ваши данные не могут быть гарантированы, и поэтому он небезопасен; по крайней мере, в больших доменах кода.