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

Если теоретически, но не практически, функция бросания будет объявлена ​​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);
}
4b9b3361

Ответ 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>..., а о практике программирования.

К сожалению, вы предполагаете, что ваши данные не могут быть гарантированы, и поэтому он небезопасен; по крайней мере, в больших доменах кода.