возврат по значению и без исключения - PullRequest
3 голосов
/ 18 марта 2012

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

class sample {
public:
  sample() noexcept { }//this doesn't throw
  sample(const sample & s) noexcept { }
  sample(sample && s) noexcept { }
  sample & operator=(const sample & s) noexcept {...}
  sample & operator=(sample && s) noexcept { ... }
  ~sample() noexcept() { }//this should never ever throw
  sample operator-() const { return *this * -1; }//assuming that there is a operator*…
  sample & operator*=(const sample & s) noexcept { ... }
};

sample operator*(sample s1, const sample & s2) { return s1 *= s2; }//same problem as with operator-…

Безопасно ли декларировать sample :: operator- как noexcept, или нет? (учитывая, что он вызывает конструктор по возвращении)

РЕДАКТИРОВАТЬ: я обновил раздел кода, так как кажется, что центральная часть вопроса была не ясна ...

Ответы [ 2 ]

2 голосов
/ 18 марта 2012

После редактирования : Ваша реализация operator- гарантированно не вызовет никаких исключений (ну, по крайней мере, если вы пометите operator* как noexcept, то есть), и это так безопасно пометить его как noexcept. Я не совсем понимаю вашу озабоченность, хотя, возможно, мне не хватает причины для вопроса. Все операции, включая потенциальную конструкцию копирования или перемещения, четко помечены noexcept ... в чем проблема?


Если вы явно не отметите его как noexcept, он не будет иметь такой квалификации. Теперь, в зависимости от реализации operator* и конструктора копирования , он может фактически никогда не выдавать, но это не делает его noexcept.

Начиная с конструктор копирования , если вы не определите его, неявно объявленный конструктор копирования будет noexcept или не зависит от того, все ли члены вашего типа noexcept ( опять же, не только то, что они не бросают, но и то, что у них есть эта квалификация)

1 голос
/ 05 июля 2012

Ваш вопрос: "Это безопасно?"Я бы скорее спросил: «Имеет ли смысл даже объявлять некоторые функции как noexcept только потому, что они не генерируют исключения?».

Строго говоря, есть две вещи, которые предлагает noexcept:

  1. Каждый может проверить во время компиляции, объявлена ​​ли ваша функция как noexcept.(На практике это полезно только в одной функции std: move_if_noexcept)
  2. Вы получаете гарантию во время выполнения, что если ваша функция тем не менее пытается выдать исключение, она не выходит из функции (потому что stdВместо этого вызывается :: terminate.

Более интересно перечислить, что noexcept делает not предложение:

  1. Автоматическая проверка во время компиляции, еслифункция на самом деле не выдает
  2. Что еще более важно, она не предлагает никакой "гарантии безопасности исключений".

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

Единственным разумным местом для использования noexcept является предоставление конструктора перемещения или назначения перемещения в вашем типе, и только если вы чувствуете, что вам нужно определить их самостоятельно, а не полагаться на версии, сгенерированные компилятором.Это полезно, потому что некоторые операции контейнера STL будут работать быстрее, потому что они используют функцию std :: move_if_noexcept в своих реализациях.

Я также рекомендую эту статью с подробностями о функциональности noexcept.

...