2

我已经用 C++ 编程几个月了,当我浏览论坛时,我注意到了一种趋势。似乎这些goto陈述通常被认为是完全错误的使用,或者只应在非常特定的情况下使用。是什么goto使它们从根本上错误的陈述?

4

2 回答 2

7

最大的原因是它使代码难以遵循。goto并不是隐含的坏;用它编写难以理解的代码很容易。

例如,您更愿意阅读哪个?这个:

int factorial(int n) {
    int result;

    if(n==0 || n==1)
        result = 1;
    else
        result = n*factorial(n-1);

    return result;
}

或这个:

int factorial(int n) {
    int result;

    if(n > 1)
        goto big;

    result = 1;
    goto end;

big:
    result = n*factorial(n-1);

end:
    return result;
} 

这两种实现对机器来说是一样的,但第一种对我们的肉眼来说要清楚得多。不过,有时goto 更清楚。例如,从 C(或 C++ 没有例外)考虑这个:

void process_big_file(FILE* foo) {
    if(possible_failure_1(foo))
        goto cleanup;

    // Do some work

    if(possible_failure_2(foo))
        goto cleanup;

    // Do some more work

cleanup:
    fclose(foo);
}

在这里,使用goto是有意义的,因为它可以让您将所有清理代码放在一个地方,并且gotos 实际上创建了一个逻辑执行流。特别是,在阅读代码时,很明显您总是 (a) 到达清理代码,并且 (b) 总是到达相同的清理代码,这在这里很重要。在没有例外的情况下,我实际上认为goto在尝试组织(例如)清理代码时这是正确的事情。

于 2013-04-28T18:28:35.793 回答
0

主要原因是这goto使得对代码的推理非常困难,如果不是不可能的话。(注意,同样的事情也适用于“隐藏”的 goto,比如使用 abreak从循环中间退出。)一般来说,如果您希望能够推断代码的正确性,您希望在每个块中输入顶部,并将其留在底部。如果无法推断代码的正确性,您就无法确定它是否正确。

于 2013-04-28T19:03:00.113 回答