多个返回语句或“goto end”

发布于 2024-11-09 06:11:45 字数 624 浏览 0 评论 0原文

什么是更好的风格/可读性?

我有一个循环读取输入并根据输入执行不同的操作,当发生错误时,我需要一个简单的return;。示例:

while( get_input() )
{
    if( input == "somethingcool" )
    {
        if( !process_somethingcool() )
            return; // <-- a couple of these
    }
    //...
    else // bad input, error handling is fancier than this, but irrelevant to the question
        return;
}
return;

那么我是否应该将单个 return; 替换为 goto end; 并在最后一个 return 的正上方放置一个标签 end:还是上面的例子?我不需要“使用 RAII”,因为 if 块中没有分配任何内容。除了风格/可读性/性能之外,这两种方式在所有意义上都是相同的?

我认为性能是相同的,但只是为了确定:是吗?

What is better stylewise/readability?

I have a loop that reads input and does different things according to the input, and when an error occurs, I need a simple return;. Example:

while( get_input() )
{
    if( input == "somethingcool" )
    {
        if( !process_somethingcool() )
            return; // <-- a couple of these
    }
    //...
    else // bad input, error handling is fancier than this, but irrelevant to the question
        return;
}
return;

So should I replace the individual return;s with a goto end; and place a label end: right above the last return in the example above or not? I am not in need of "use RAII" because nothing is allocated in the if blocks. Both ways would be identical in all senses of the word, except for the style/readability/performance?

I would suppose performance is identical, but just to be sure: is it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

就是爱搞怪 2024-11-16 06:11:45

对于 C,goto 是合理的(它在 Linux 内核中广泛使用),因为您可以通过单点返回来增强可读性。

对于 C++,因为任何事情都有可能引发异常,所以您隐式地具有多个返回点,因此您应该始终使用具有多个返回的 RAII 模型。

For C, goto is reasonable (it's used widely in the Linux kernel) as you can enhance readability with a single point of return.

For C++, because you have the possibility of anything throwing an exception, you implicitly have multiple points of return so you should always use the RAII model with multiple returns.

何止钟意 2024-11-16 06:11:45

你想挑起一场宗教战争吗?

说真的,有时候 goto 是最好的选择。二十年来,我见过大约 3 或 4 个。多次返回并不一定是邪恶的,但如果你必须重复大量的清理代码,那么它们就会变得非常混乱。

很多时候,您可以重构代码以使这样的选择变得不必要。在没有看到代码的情况下很难提出具体的建议,但也许是这样的:

void f()
{
   bool bDone=false;
   while (!bDone && get_input())
   {
      if (input == "cool")
      {
         process_cool();
         bDone = true;
      }
      else if (input == "unfinished")
      {
         process_something();
      }
      else
      {
          // error
          bDone = true;
      }
   }
}

重构的一个很大的帮助是确保循环内没有几十行。如果您有大量工作要做,请将其分解为函数并从 while 循环中调用少量函数。

请记住,单个函数应该只做一件事。

强烈推荐的另一种方法是使用异常来处理错误情况,但如果您刚刚完成处理,则使用异常是不好的风格,因此这可能无法完全解决您的问题。

如果您仍然感到困惑,请考虑发布更实际的代码块,我们也许可以建议如何最好地处理问题。

祝你好运!

Are you trying to start a religious war?

Seriously, there are occasionally places where a goto is the best choice. In twenty years, I've seen around 3 or 4. Multiple returns are not necessarily evil, but if you have to repeat a lot of cleanup code then they become pretty messy.

Very often, you can refactor the code to make such a choice unnecessary. It is hard to make specific suggestions without seeing your code, but maybe something like this:

void f()
{
   bool bDone=false;
   while (!bDone && get_input())
   {
      if (input == "cool")
      {
         process_cool();
         bDone = true;
      }
      else if (input == "unfinished")
      {
         process_something();
      }
      else
      {
          // error
          bDone = true;
      }
   }
}

A big help in refactoring is to make sure you don't have dozens of lines inside the loop. If you have a lit of work to do, break it into functions and call a small number of functions from within the while loop.

Remember that a single function should only do one thing.

Another approach that is highly recommended is to use exceptions to handle error conditions, but it is bad style to use an exception if you have just finished processing, so this might not completely solve your problem.

If you are still confused, consider posting a more realistic chunk of code and we may be able to suggest how best to handle things.

Good Luck!

橘虞初梦 2024-11-16 06:11:45

就我个人而言,我喜欢使任何块的内容尽可能小。一行调用另一个函数是理想的(继 Bob Martin 的《简洁代码》之后)。

我会选择您没有提出的选项:

while(get_input()) {
    if(!process_input(input)) {
         break;
    }
}

其中 process_input 将选择适当的 process_... 函数,返回返回的任何内容,如果输入错误则返回 false。

Personally, I like to keep the content of any blocks as small as possible. One line, calling out to another function is ideal (after Bob Martin's Clean Code).

I'd go with an option you haven't proposed:

while(get_input()) {
    if(!process_input(input)) {
         break;
    }
}

Where process_input would select the appropriate process_... function, returning whatever that returns, or false if there is bad input.

握住你手 2024-11-16 06:11:45

当你想回来的时候就回来吧。 C++ 语言可以处理这个问题,并且它是编写代码的最直观的方式。

在某些语言中,清理必须在使用站点完成,因此将“清理”阶段集中在您“转到”的单个块中可能是个好主意。在C语言中,这种习惯用法很常见。

在 C++ 中,当资源超出范围时,资源会在其析构函数中自行清理。因此,在使用现场,什么都不用做,最简单、最干净、最不容易出错的解决方案就是使用多个 return 语句。

Just return when you want to return. The C++ language can handle that, and it is the most intuitive way to write your code.

In some languages, cleanup has to be done at the use site, and so it may be a good idea to centralize the "cleanup" phase in a single block that you "goto". In C, this idiom is common.

In C++, resources are cleaned up by themselves in their destructors when they go out of scope. And so at the use site, nothing needs t obe done, and the easiest, cleanest and least error-prone solution is to just have multiple return statements.

权谋诡计 2024-11-16 06:11:45

多个返回语句实际上是一种很好的风格,并且几乎总是比尝试拥有单个返回点生成更干净的代码。 goto 在 C++ 中非常无用,因为(除了它们的其他问题)它们无法跳过初始化,这可能会迫使您在远离其使用点的地方初始化事物,这也是不好的风格。

Multiple return statements are actually good style and almost always produce cleaner code than trying to have a single return point. gotos are pretty useless in C++ as (apart from their other problems) they can't jump over initialisations, which possibly forces you to initialise things away from their point of use, which is also bad style.

找回味觉 2024-11-16 06:11:45

风格和可读性会让我使用异常来处理错误情况。你的调用者如何知道你的方法是否被正确调用?

也就是说:goto 不应该用于此目的; return 是更好的选择。如果您需要在例程结束时执行任何操作,无论它为何退出 - 那么您应该抛出异常并使用 catch 块。

Style and readability would lead me to use exceptions to handle error conditions. How is your caller to know whether your method was invoked correctly?

That said: goto shouldn't be used for this; return is the far better option. If you need to do anything at the end of your routine, regardless of why it dropped out - then you should throw exceptions and use a catch block.

云朵有点甜 2024-11-16 06:11:45

return 通常优先于 goto;通常,标签的批评者无法提出任何实际论据来支持他们的教条。1

但是,您的情况更加明确:您为什么会选择<代码>转到?两种解决方案都是等效的,只是 goto 要求您在函数结束之前编写 end:,这会占用空间并且无缘无故地看起来很难看。

因此,在提供的两个选项中,我推荐 return。也就是说,我还建议认真考虑在回答这个问题时给出的其他建议(例外情况,并限制条件的“嵌套性”)。


1 或者,如果他们这样做,通常是“goto 让你的对象挂起”,这是不正确的(根据 C++0x FDIS)。 goto 不会破坏 RAII 模型

return is generally preferred to goto; usually, detractors of labels are unable to come up with any actual argument to support their dogma.1

However, your case is more clear-cut: why would you pick the goto? Both solutions are equivalent, except that the goto requires you to write end: just before the end of the function, taking up space and looking ugly for no reason.

Therefore, out of the two options presented, I'd recommend the returns. That said, I'd also recommend seriously considering the other suggestions given in responses to this question (exceptions, and limiting the "nestiness" of your conditionals).


1 Or, if they do, it's usually something along the lines of "goto leaves your objects hanging", which is not true (as per 6.6/2 in the C++0x FDIS). goto does not break the RAII model.

我一直都在从未离去 2024-11-16 06:11:45

goto End; 很好,部分原因在于可读性,而且还因为如果您后来意识到在关闭函数之前需要发生一些事情,例如释放内存或释放资源,您可以集中这些事情处理而不是复制粘贴它。

The goto End; is nice in part because of readability but also because if you realize later there are things that need to happen before you close the function, freeing memory or releasing resources for example, you can centralize that process instead of copy pasting it.

西瓜 2024-11-16 06:11:45

实际上,不建议使用goto。它会产生代码可读性问题。最好使用 break; 语句来退出循环并在代码末尾返回。这是标准程序。

while( get_input() )
{
    if( input == "somethingcool" )
    {
        if( !process_somethingcool() )
            break; // <-- a couple of these
    }
    //...
    else // bad input, error handling is fancier than this, but irrelevant to the question
        break; //although its better if you handle it somehow here.
}
return;

Actually, its not advisable to use goto. It generates problems in readability of the code. Better use a break; statement where you want to leave the loop and return at the end of the code. That's the standard procedure.

while( get_input() )
{
    if( input == "somethingcool" )
    {
        if( !process_somethingcool() )
            break; // <-- a couple of these
    }
    //...
    else // bad input, error handling is fancier than this, but irrelevant to the question
        break; //although its better if you handle it somehow here.
}
return;
戈亓 2024-11-16 06:11:45

为什么不使用“保护子句”(通过反转逻辑)而不是嵌套的 if 来构建代码。那么使用 goto 的整个问题就变得毫无意义了。

while( get_input() )
{
    if( input != "somethingcool" )
    {
        return; //handle error
    }
    if( !process_somethingcool() )
        return; //handle error
    }
}
return; //success

Why not structure your code using "guard clauses" (by reversing the logic) instead of the nested ifs. Then the whole question of using goto becomes moot.

while( get_input() )
{
    if( input != "somethingcool" )
    {
        return; //handle error
    }
    if( !process_somethingcool() )
        return; //handle error
    }
}
return; //success
宁愿没拥抱 2024-11-16 06:11:45

两者都不。您应该将代码重构为可读的内容
并且可维护。我见过的每一个案例(而且我见过很多)
程序员需要一个goto,并且大多数情况下
他需要多次回报(以及所有情况
return 已嵌套在循环中)可以通过以下方式更好地解决
将代码重构为单独的、更简单的函数,每个函数
它在函数末尾有一个返回。 (多种的
对于非常简单的函数,返回有时是合理的;例如
如果函数中唯一的语句是,我将使用它们
一个 switch,每个 case 都以 return 结束。)

Neither. You should refactor the code into something readable
and maintainable. Every case I've seen (and I've seen a lot)
where the programmer has needed a goto, and most of the cases
where he's needed multiple returns (and all cases where the
return has been nested in a loop) would have be better solved by
refactoring the code into separate, simpler functions, each of
which had a single return at the end of the function. (Multiple
returns are sometimes justified for very simple functions; e.g.
I'll use them if the only statement in the function is
a switch, and every case ends with a return.)

帅气称霸 2024-11-16 06:11:45

恕我直言,使用多个返回并且不要使用 goto。那些使用goto的人也会放火烧狗。

IMHO use multiple returns and do not use goto. Those who use goto, also set dogs on fire.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文