多个返回语句与多个goto语句:哪一个更可取?

时间:2010-08-21 07:00:21

标签: c++

我读到多个返回和多个goto语句都是糟糕的编程习惯。我有一个功能,可以检测到8种类型的错误。如果出现错误,我应该返回错误代码还是应该使用goto statment转到函数结束并从那里返回。 每当从函数返回之前需要释放内存时,我认为最好有一个goto结尾并在函数结束时释放内存(这样只有一个空闲就足够了)

但是,在我的功能中,没有分配内存。 在这种情况下哪一个更好?多个返回或多个goto语句? 或者我们可以避免两者吗?

编辑:避免两者的一些方法是,将参数传递给可以存储errorType的函数。在继续进行之前,可以在功能内检查相同内容。但这也使代码变得丑陋。

9 个答案:

答案 0 :(得分:6)

我认为多个return语句很好,在处理内存分配和释放时,使用智能指针等处理内存管理的东西几乎总是值得的。

答案 1 :(得分:4)

如果你看一下如何在C代码中使用goto,比如Linux内核,它会在从函数返回之前用来进行资源清理。多个标签用于以与采集相反的顺序释放资源,代码的早期部分跳转到以后转到标签。

在C ++中,您应该使用RAII来管理资源。然后你可以使用多个return语句,任何需要的清理都会自动发生。

但是,如果您检测到许多不同类型的错误,您的功能/方法可能会显示低cohesion,您可能需要考虑将功能/方法拆分为更小的单位。这可能会使错误处理变得更加困难,因为您现在可能有更复杂的返回路径,因此为了避免这种繁琐的错误处理,请使用异常而不是错误返回值。这将与RAII很好地吻合以自动清理资源。

答案 2 :(得分:3)

避免自己做内存管理。您可能正在使用默认分配器,而new将抛出异常。在RAII之后编写C ++代码并包装在类中分配资源的所有代码。然后就不需要手动释放内存了

答案 3 :(得分:2)

任何具有多个gotoreturn语句的方法/过程都可以转换为一个(或多个)具有一个退出点且没有goto语句的其他方法。 / p>

例如:

void proc1(...) {
    // allocate thing
    if (x) {
        ...
        // free thing
        return;
    } 
    ...
    // free thing
    return;
}

可以改写为:

void proc1(...) {
    // allocate thing
    proc1a(...);
    // free thing
}

void proc1a(...) {
    if (x) {
        ...
        return;
    } 
    ...
    return;
}

通过一些思考,您可以避免每个return (IMO kludgy)goto解决方法的重复内存管理。

您选择的替代方案最终应该是通过使代码可读和可维护的目标来激励,而不是通过关于多个返回或者糟糕的错误的教条。

答案 4 :(得分:1)

我不会推荐goto,因为你会被严重避开(尽管我认为有一些例外,其中goto是一种合理的方法)。

多次退货很好。我倾向于保留这些作为保护条款。这是函数实现的第一部分由一个或多个if(x) return;语句组成的地方。这些尝试识别不良参数或其他错误条件,从而无需再进行任何处理。

guard子句应该有助于将if-else嵌套保留到其余代码的最小值。我试着通过使用临时结果来限制本节的一个返回。如果您仍然发现嵌套很深或多次返回会有所帮助,那么该函数可能会尝试做太多而且应该重构为多个辅助函数。

答案 5 :(得分:1)

在我看来,多次退货很好而且不那么复杂。多个条件检查语句会降低性能并不必要地增加代码大小。我总是习惯根据情况多次退货。根据我的说法,这不是一个糟糕的编程习惯。

答案 6 :(得分:0)

您可以使用另一个参数来表示错误,就像您说的那样,甚至返回保留所有结果的 struct 。我曾经写过一个BTree类并使用struct方法返回search_results(我保留了类似于:Did_I_find_it或者元素的位置和其他一些东西。)我更喜欢认为这些参数是用于输入和返回语句的输出函数。

应该真的避免转到。这是最混乱的解决方案。

答案 7 :(得分:0)

NONE我会说

  • 您可能希望将split方法转换为更小的方法

  • 人们有时会使用do{..}while(0)循环与break组合。这可以确保该方法仅从一个地方返回。除非您没有看到任何其他选项,否则应避免使用goto

示例代码:

int myMethod(){
  int retval = 0;
  do{
      if(...){
         retval = 1;
         break;
      }
      else if(...){
         retval = 2;
         break;
      }
      else{
         retval = 3;
         break;
      }
   }while(0);
  return retval;
}

答案 8 :(得分:0)

请注意,使用goto可能会禁用函数中的某些编译器优化。因此,没有充分理由使用goto可能会导致代码效率降低。

此外,恕我直言,使用return语句而不是多个goto语句会产生更易读/​​可查看的代码。使用goto,你必须搜索目标标签,并确保nobobdy真正使用goto来混淆代码。

而且,在C ++中,你有一些强大的语言结构,比如异常和具有析构函数的对象,它们在scope-exit上进行资源清理 - 因此,goto的使用非常有限。