C++ 编程
外观
goto
关键字不鼓励使用,因为它使得难以追踪程序逻辑,从而导致错误。goto
语句导致当前执行线程跳转到指定的标签。
- 语法
label:
statement(s);
goto label;
在一些罕见情况下,goto
语句允许编写整洁的代码,例如,在处理多个退出点导致函数退出时的清理代码时(并且异常处理或对象析构函数不是更好的选择)。除了这些罕见情况,无条件跳转的使用通常是复杂设计的征兆,因为存在多层嵌套语句。
在例外情况下,例如在进行大量优化时,程序员可能需要对代码行为有更多控制;goto
允许程序员指定执行流直接且无条件地跳转到所需的标签。标签 是在函数中其他地方给标签语句起的名称。
例如,goto
可以用来跳出两个嵌套循环。这个例子在将第一个遇到的非零元素替换为零后跳出循环。
for (int i = 0; i < 30; ++i) {
for (int j = 0; j < 30; ++j) {
if (a[i][j] != 0) {
a[i][j] = 0;
goto done;
}
}
}
done:
/* rest of program */
虽然简单,但它们很快就会导致代码难以阅读和维护。
// snarled mess of gotos
int i = 0;
goto test_it;
body:
a[i++] = 0;
test_it:
if (a[i])
goto body;
/* rest of program */
比等效的
for (int i = 0; a[i]; ++i) {
a[i] = 0;
}
/* rest of program */
Goto 通常用于性能至关重要的函数,或在机器生成的代码(例如由 yacc 生成的解析器)的输出中。
goto
语句几乎应该始终避免使用,但有一些罕见的情况可以提高代码的可读性。其中一种情况是“错误部分”。
示例
#include <new>
#include <iostream>
...
int *my_allocated_1 = NULL;
char *my_allocated_2 = NULL, *my_allocated_3 = NULL;
my_allocated_1 = new (std::nothrow) int[500];
if (my_allocated_1 == NULL)
{
std::cerr << "error in allocated_1" << std::endl;
goto error;
}
my_allocated_2 = new (std::nothrow) char[1000];
if (my_allocated_2 == NULL)
{
std::cerr << "error in allocated_2" << std::endl;
goto error;
}
my_allocated_3 = new (std::nothrow) char[1000];
if (my_allocated_3 == NULL)
{
std::cerr << "error in allocated_3" <<std::endl;
goto error;
}
return 0;
error:
delete [] my_allocated_1;
delete [] my_allocated_2;
delete [] my_allocated_3;
return 1;
这种结构避免了处理错误的来源,并且比使用控制结构的等效结构更简洁。因此,它不易出错。