LINUX.ORG.RU

Пиатницо, return statement


0

1

Привет.
1.

int funcA()
{
   if () return 2;
   if () return 1;
   // do some more
   return 0;
}

2.

int funcA()
{
   error = 0;
   do {
      if () {
         error = 2;
         break;
      }
      if () {
         error = 1;
         break;
      }
      // do some more
   }
   while(0);
   return error;
}

3.

int funcA()
{
   if () goto ERROR;
   if () goto ERROR;
   // do some more
ERROR:
   return 0;
}

Ваш вариант и аргументы? ) Дискасс! =)

★★★★★

Есть ещё вариант со свичом и мапом:

int value = DEFAULT;
if() value = ONE;
if() value = TWO;
switch(value) {...} // return map[value];

schizoid ★★★
()
Ответ на: комментарий от schizoid

goto considered harmful

лол

вообще считается, что в подпрограмме должна быть одна точка выхода. к счастью считается не мной и я пишу return где нужно, а не где по ветхому завету.

x0r ★★★★★
()
Ответ на: комментарий от schizoid

Поясни целесообразность второго варианта и его выгоды по сравнению, например, с первым.

Плюсую этого господина ;)

UVV ★★★★★
() автор топика
Ответ на: комментарий от x0r

Одна точка выхода, в принципе, хорошая идея. Я привёл выше вариант с мапом и свичом - разделяется логика выбора и логика выхода.

schizoid ★★★
()
Ответ на: комментарий от schizoid

по моему игра с придумыванием где кошернее поставить return не стоит свеч. надо выйти - сделай cleanup и выйди.

плохо становится в случае большой вложенности операторов, когда условие выхода плохо прослеживается. но тут скорее проблема имеено в нагромождении if/while/for/switch.

x0r ★★★★★
()
Ответ на: комментарий от schizoid

Там конечно do {} while(0) абсолютно лишний, но этот вариант нужет, если надо сохранить ret-value. e.g.:

int
foo()
{
    int ret;

    ret = read(…);
    /* do something important */

    return ret;
}

beastie ★★★★★
()

в ведре предпочитают третий вариант.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от beastie

Ну это же совсем другое дело, на второй вариант вообще не похоже. Да, так тоже иногда полезно.

schizoid ★★★
()

Если надо освобождать ресурсы - 3. Если не надо - 1. Если начальник идиот и надо освобождать ресурсы - 2.

Legioner ★★★★★
()
raise SomeException
Deleted
()

1. Так проще и нагляднее всего (субъективное мнение).

AIv ★★★★★
()

В чистом Си третий вариант вполне Ок, по причине отсутствия исключений и автоматического управления памятью.

maxcom ★★★★★
()

Надо к такому добавлять тег «скучный холивар».

quiet_readonly ★★★★
()
Ответ на: комментарий от AIv

Я так понял, речь про С. В С++ естественно только первый вариант.

Legioner ★★★★★
()

Ну т.к. язык не указан, это может быть и С++. Там однозначно вариант 1, т.к. вариант 3 легко приведёт к куче вложенных блоков (чтобы избежать пропуска конструкторов из-за goto) и замусориванию кода явным std::move, вариант 2 - это случай больного начальника.

Begemoth ★★★★★
()
Ответ на: комментарий от Legioner

golang defer

что бы всегда 1ый.

ну и ТСу : имхо 1ый ибо минимизация вложенности (то что код do-части в результате исполняется только при ~(||(iffilters)) должно понимать )

qulinxao ★★☆
()
Ответ на: комментарий от x0r

в подпрограмме должна быть одна точка выхода

интересна история развития сей «аксиомы»

т.е какие реальные ограничения реализации делали полезной такую эвристику.

и интересно какие изменения в железках/софте сделали/(сделают для всё ещё исповедующих сию эвристику) бесполезной/(и даже вредной ибо ограничение без пользы есть прямой ущерб)

это правило.

1. имхо когда одна точка выхода - легче в примитивном отладчике делать стоп на «перед выходом из функции» 2... ?

qulinxao ★★☆
()

Точка выхода лучше когда одна, goto применять не рекомендуется. Так что практически единственный вариант

return (cond1) ? A : (cond2) ? B : something;

или так, если something слишком неимоверен

if ((err=1, !cond1) && (err=2, !cond2)) {
  someting;
  err = !1; // за всё время службы ни одного еррора не обнаружено
}

return err;
auto12884838
()

1 или 3

но вот ещё тупой вариант для дискасса :)

int funcA()
{
  int ret = 0;
  if ()
  {
    if ()
    {
      if ()
      {
      }
      else
      {
        //free resource 3
        //free resource 2
        //free resource 1
        ret = 3;
      }
    }
    else
    {
      //free resource 1
      //free resource 2
      ret = 2
    }
  }
  else
  {
    //free resource 1
    ret = 1;
  }

  return ret;
}
Harald ★★★★★
()
Ответ на: комментарий от qulinxao

интересна история развития сей «аксиомы»

т.е какие реальные ограничения реализации делали полезной такую эвристику.

Вот и выросло поколение, не слыхавшее про Дейкстру.

auto12884838
()

ТС, а зачем первый?

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

a = allocate_foo();
if (a == NULL) goto lol1;
a->bar = allocate_bar();
if (a->bar == NULL) goto lol2;

if (doit (a) == 0) return OK;

// Что-то не так
free(a->bar);
lol2: free(a);
lol1: return NOMEM;
anonymous
()
Ответ на: комментарий от Harald

В Бейсике тоже можно выделять динамическую память. А ещё там есть спрайты, массивы для уровней.. Их тоже нужно занулять. И файлы.

schizoid ★★★
()
Последнее исправление: schizoid (всего исправлений: 1)
Ответ на: комментарий от auto12884838

не по адресу. тему у мя с большой цитатой из него легко посмотреть про «заточеность » людей на статические картины в отличии от динамически во времени разварачивающихся процессов.

и вопрос обрати внимание - ни «кто и насколько велик автор сей аксиомы/эвристики»

а каковы условия при которых эвристика реально полезна.

и каковые условия при которых даже самый упёртый начётчик откажется от следования ей.

qulinxao ★★☆
()

вдоль..если есть разница - это проблема компилятора

MKuznetsov ★★★★★
()
Ответ на: комментарий от qulinxao

не по адресу. тему у мя с большой цитатой из него легко посмотреть про «заточеность » людей на статические картины в отличии от динамически во времени разварачивающихся процессов.

Яничегонепонял.DBF. Если ты ссылаешься на какое-то конкретное обсуждение или цитату, делись ссылкой.

и вопрос обрати внимание - ни «кто и насколько велик автор сей аксиомы/эвристики»

а каковы условия при которых эвристика реально полезна.

Расставляй пожалуйста приоритеты правильно. Я ссылаюсь на Дейкстру не потому что он велик или мой родственник. Он велик и на него ссылаются именно потому что у него всё расписано и обосновано.

и каковые условия при которых даже самый упёртый начётчик откажется от следования ей.

При каких реально вредна, можно легко увидеть в любом листинге например программы расчёта квантовой механики на фортране для DEC. Я не исключаю возможности, когда goto использовать не так уж и вредно, но всё же предпочитаю обходиться без него. В простых случаях он помогает незначительно, а в сложных всё усложняет, и легко перейти грань, когда твоя прога становится похожа на тот самый фортрановский листинг.

auto12884839
()

2.

int funcA()
{
  error = 0;
  if () {
    //do first
    error = 2;
  }
  if (!error) {
    //do second
    error = 1;
  }
  // do some more
  return error;
}

anonymous
()
Ответ на: комментарий от auto12884839

Я не исключаю возможности, когда goto использовать не так уж и вредно, но всё же предпочитаю обходиться без него. В простых случаях он помогает незначительно, а в сложных всё усложняет, и легко перейти грань, когда твоя прога становится похожа на тот самый фортрановский листинг.

Я знаю только полтора случая, когда goto действительно помогает.

  1. Освобождение ресурсов на переносимой чистой Сишечке. Повторять cleanup-код, а затем return — можно забыть cleanup-код. Писать сотню «if (!err)» ещё более некрасиво, чем один «err = 42; goto cleanup;». Но это проблемы Сишечки, потому что там явный memory-management.
  2. (Спорный.) Для выхода из глубоко вложенных циклов, потому что сентинел-условия выглядят уродско вне зависимости от контекста, да простят меня верующие в теорему Бёма—Якопини. Ну и есть мнение, что достаточно break и правила: «Если у вас больше трёх уровней вложенности, то ваш код говно и его надо рефакторить».

В остальных случаях и в языках с нормальным управлением памятью и ресурсам бить по пальцам. Но Сишечку не трогайте, пожалуйста.

ilammy ★★★
()
Ответ на: комментарий от Deleted

Да я про си подумал, в с++ и джаваподобных гото мне хотелось использовать, только чтобы из циклов выпрыгивать, да и то, чтобы карму не портить — в функцию выносил обычно тело цикла. Я вообще только недавно узнал, что в джаве гото не работает, а ключевое слово он по какому-то недоразумению.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

тамже пгавославный break есть, по сути тотже готу для сих целей, токо зело неочевидный

The break statement terminates the labeled statement; it does not transfer the flow of control to the label. Control flow is transferred to the statement immediately following the labeled (terminated) statement.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Legioner

и джаваподобных гото мне хотелось использовать, только чтобы из циклов выпрыгивать

Labeled break :) Но путь с функцией более правильный, да.

ключевое слово он по какому-то недоразумению.

Это специально, чтобы не использовали и не называли свои сущности так.

ilammy ★★★
()
Ответ на: комментарий от ilammy

Писать сотню «if (!err)» ещё более некрасиво, чем один «err = 42; goto cleanup;».

Писать сотню «if (!err)» вместо одного «if (!err)» или одного «err = 42; goto cleanup;» действительно некрасиво.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.