Я предпочитаю первое, до того момента, когда у меня есть набор макросов для обработки общих случаев (и, как правило, для одновременного утверждения в целях отладки). Недостатком этого подхода является то, что типы возвращаемых функций должны быть достаточно однородными, чтобы использование макросов было одинаковым; плюс в том, что использование / эффект очень понятен. Так, например, мой код может выглядеть так:
class A;
void fun(A* p)
{
ASSERT_NONZERO_RETURN_ON_FAIL( p );
B* pB = p->getB();
ASSERT_NONZERO_RETURN_ON_FAIL( pB );
.......
}
Это приводит к гораздо более читаемому коду, который также предупреждает вас об ошибках. Кроме того, в качестве дополнительного бонуса вы можете легко отключить проверку в сборке выпуска, если обнаружите, что вы цените увеличение предельной скорости по сравнению со значением проверок во время выполнения.
Добавлено примечание: по моему опыту, некоторые люди говорят, что множественные точки возврата из функций являются плохими, потому что они явно перераспределяют ресурсы перед выходом из функции, и, таким образом, вы не хотите дублировать код де-выделения , Если вы используете RIIA правильно и равномерно, это не должно быть проблемой. Поскольку это то, что я всегда стараюсь делать, для меня предпочтительнее несколько точек возврата.