та же операция в множественном операторе if, как уменьшить избыточность кода

Оператор удаления, приведенный ниже, является избыточным кодом.

int *a = new int[100]
if (!doSomething1(a))
delete[] a
return
if (!doSomething2(a))
delete[] a
return
if (!doSomething3(a))
delete[] a
return

return

Одна альтернатива, которую я придумала:

if(doSomething1(a) || doSomething2(a) || doSomething3(a))
;
delete[] a;
return;

Но это не подходит в ситуации, когда я хочу добавить инструкции, указанные для doSomething1 (), например,

if(!doSomething1(a))
foo;
delete[] a;
return;
if(!doSomething2(a))
delete[] a;
return;

Мне сказали, что есть по крайней мере 5 способов уменьшить этот вид избыточности кода. Так какие-нибудь предложения?


обновить, еще один вопрос:
тот же вопрос, давайте ограничим область только C, отметим изменение логики процесса.

char *a = (char*)malloc(100*sizeof(char));
if(doSomething1(a))
foo;
free(a)
return;
if(doSomething2(a))
free(a)
return;
if(doSomething3(a))
free(a);
return;
free(a);
return

0

Решение

Зачем вам нужно что-либо вручную удалять? Это C ++, поэтому мы можем использовать деструкторы и RAII.

std::vector<a>(100);
if (!doSomething1(a))
return;
if (!doSomething2(a))
return;
if (!doSomething3(a))
return;

В более общем плане: если что-то должно произойти, когда вы покидаете область действия, то делайте это в деструкторе автоматического объекта в этой области действия.

Но почему вы используете возвращаемые значения для обозначения сбоя? Это C ++, поэтому мы можем использовать исключения:

std::vector<a>(100);
doSomething1(a);
doSomething2(a);
doSomething3(a);
2

Другие решения

«RAII» и «выход из области» были бы хорошими поисковыми терминами для Google или SO. Например, посмотрите на Boost.ScopeExit или альтернативы этому. Идея состоит в том, что вы создаете локальный объект и оставляете его деструктор сделать очистку или «наконец» код.

Вот попытка применить идиому непосредственно к вашему примеру, сведенную к минимуму (без проверки ошибок и тому подобного):

class AutomaticDeleter
{
public:
AutomaticDeleter(int *a) : a(a) {}
~AutomaticDeleter() { delete[] a; }
int *GetWrappedPointer() const { return a; }
private:
int *a;
};

// ...

AutomaticDeleter automatic_deleter(new int[100]);

if (!doSomething1(automatic_deleter.GetWrappedPointer()))
return;
if (!doSomething2(automatic_deleter.GetWrappedPointer()))
return;
if (!doSomething3(automatic_deleter.GetWrappedPointer()))
return;

И, конечно, я должен отметить, что это всего лишь пример того, что вы Можно делай не то что ты должен делать при применении идиомы к указателю, особенно тот, который возвращается из new[], В реальной жизни вы бы использовали std::vector<int> и покончим с этим. Идиома имеет гораздо более интересные и полезные приложения.

1

bool failure;

int *a = new int[100]
if ( failure = !doSomething1(a))
//...
if ( !failure && ( failure = !doSomething2(a) ) )
//...
if ( !failure && ( failure =!doSomething3(a) ) )
//...

if ( failure )
{
delete []a;
return;
}
//,,,

return
0

do {
if (doSomething1(a) && doSomething2(a) && doSomething3(a)){
break; /*all good: move outside the dummy loop*/
}
/*one of the functions failed*/
delete[] a;
return;
} while (false);

это один из способов. Я полагаюсь на то, что if оценивает утверждения строго слева направо и останавливает оценку один раз в false достигнуто

(Эта идиома довольно часто используется в C; см. Исходный код ядра Unix).

0
По вопросам рекламы [email protected]