Иногда ваш компилятор не может сделать вывод, что ваша функция на самом деле не имеет отсутствия пропущенного возврата. В таких случаях существует несколько решений:
Предполагать
if (foo == 0) {
return bar;
} else {
return frob;
}
Реструктурируйте свой код
if (foo == 0) {
return bar;
}
return frob;
Это хорошо работает, если вы можете интерпретировать оператор if как своего рода брандмауэр или предварительное условие.
прервать()
(см. комментарий Дэвида Родригеса.)
if (foo == 0) {
return bar;
} else {
return frob;
}
abort(); return -1; // unreachable
Соответственно вернуть что-то другое. Комментарий сообщает коллегам-программистам и вам самим, почему это здесь.
бросать
#include <stdexcept>
if (foo == 0) {
return bar;
} else {
return frob;
}
throw std::runtime_error ("impossible");
Не контрмера: единая точка выхода функции
Не возвращайтесь к одному возврату для каждой функции, также известному как точка выхода с одной функцией. обходной путь. Это устарело в C++, потому что вы почти никогда не знаете, где функция выйдет:
void foo(int&);
int bar () {
int ret = -1;
foo (ret);
return ret;
}
Выглядит красиво и похоже на SFEP, но реверс-инжиниринг стороннего libfoo
показывает:
void foo (int &) {
if (rand()%2) throw ":P";
}
Кроме того, это может означать ненужную потерю производительности:
Frob bar ()
{
Frob ret;
if (...) ret = ...;
...
if (...) ret = ...;
else if (...) ret = ...;
return ret;
}
так как:
class Frob { char c[1024]; }; // copy lots of data upon copy
Кроме того, каждая изменяемая переменная увеличивает цикломатическую сложность вашего кода. Это означает больше кода и больше состояния для тестирования и проверки, что, в свою очередь, означает, что вы высасываете больше состояния из мозга сопровождающего, что, в свою очередь, означает снижение качества мозга сопровождающего.
И последнее, что не менее важно: некоторые классы не имеют конструкции по умолчанию, и вам придется писать действительно фиктивный код, если это вообще возможно:
File mogrify() {
File f ("/dev/random"); // need bogus init
...
}
Не делай это.
person
Sebastian Mach
schedule
05.03.2012
abort(); return -1; // unreachable
просто для того, чтобы заглушить предупреждение [и убедиться, что строка на самом деле не достигнута с помощьюabort
] - person David Rodríguez - dribeas   schedule 05.03.2012abort
правильно аннотирован (__attribute__((noreturn))
для gcc и Clang), то оба должны обнаружить, чтоabort
никогда не возвращается, и, таким образом, это должно отключить предупреждение. Другим компиляторам потребуются собственные специальные аннотации. - person Matthieu M.   schedule 05.03.2012