Лучший способ вернуться рано из функции, возвращающей ссылку - PullRequest
8 голосов
/ 18 ноября 2009

Допустим, у нас есть функция вида:

const SomeObject& SomeScope::ReturnOurObject()
{
    if( ! SomeCondition )
    {
        // return early
        return  ;
    }

    return ourObject;
}

Ясно, что в приведенном выше коде есть проблема: если условие не выполняется, у нас возникает проблема с тем, как вернуться из этой функции. Суть моего вопроса в том, как лучше всего справиться с такой ситуацией?

Ответы [ 14 ]

1 голос
/ 18 ноября 2009

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

  • Если копируемый объект не дорого, вернуть копию
  • Если копирование обходится дорого, верните Уста-указатель. Вернуть NULL в случае отказ.
0 голосов
/ 16 ноября 2011

Это та же самая ситуация, что и встроенный оператор C ++ dynamic_cast<>. Он может приводить либо к типу указателя, либо к ссылочному типу. Когда это тип указателя, он возвращает NULL при ошибке. Когда это ссылочный тип, он выдает исключение std::bad_cast при ошибке. Следуя тому же примеру, вы бы сгенерировали исключение.

0 голосов
/ 18 ноября 2009

При настройке функции вы должны вернуть SomeObject или вызвать исключение. Если вы хотите сделать что-то еще, вам нужно изменить функцию. Других вариантов нет.

Если SomeCondition никогда не будет ложным, тогда вы можете удалить тест из кода и вместо него вставить assert, либо вы можете оставить тест и вызвать исключение. (Я не рекомендую просто игнорировать такую ​​возможность, поскольку «никогда не ложь» почти всегда означает «никогда не ложь, если что-то плохое не произошло и не было обнаружено», и если его стоит проверить в любых условиях, стоит его обнаружить.)

Существует возможность возврата какого-либо нулевого объекта. Для этого полезны указатели, поскольку существует очевидное нулевое значение, которое проверяет ложь, но вы можете передать флаг обратно в качестве параметра out или вернуть специальный объект, предназначенный для нулевого значения. Затем вам нужно будет проверять возвращаемое значение при каждом вызове, чтобы оно было значимым, и это вряд ли будет меньше хлопот, чем assert или throw.

Если бы я делал это, это зависело бы от SomeCondition. Если он имеет побочные эффекты или его нетрудно рассчитать, протестируйте и сгенерируйте исключение, если false. Если вычисление обременительно, используйте assert, чтобы вам не приходилось делать это на производстве, и забудьте об этом, кроме этого.

0 голосов
/ 18 ноября 2009

Я считаю, что ответ зависит от того, являетесь ли вы тем программистом, который считает исключения плохими и никогда не хочет их использовать или нет. Если вы их используете, И это действительно исключительное условие, то должно быть выброшено исключение. Да, пользователи должны иметь дело с этим, но скрывать ошибку, притворяясь, что ничего не произошло, просто не вариант. Но если вы никогда не используете исключения, просто верните указатель или логическое значение и добавьте неконстантную ссылку на SomeObject в свою функцию. Оба решения просты, но кто сказал, что чрезмерно усложняющие вещи делают код лучше?

...