什么是更重要的可读性或速度?
示例:
假设您用一种方法创建了很多资源,如果某些操作失败,则必须释放成功创建的资源。您是否愿意在常规清理标签中这样做,以便在操作失败后释放任何资源或释放创建的资源?
样式1:
void foo(void)
{
void* res1, res2, res3;
res1 = malloc(1);
if(res1 == NULL)
return; //operation failed
res2 = malloc(1);
if(res2 == NULL)
{
free(res1);
return;
}
res3 = malloc(1);
if(res3 == NULL)
{
free(res1);
free(res2);
return;
}
}
样式2:
void foo(void)
{
void* res1 = NULL, *res2 = NULL, *res3 = NULL;
res1 = malloc(1);
if(res1 == NULL)
goto lbl_clean_up; //operation failed
res2 = malloc(1);
if(res2 == NULL)
{
goto lbl_clean_up;
}
res3 = malloc(1);
if(res3 == NULL)
{
goto lbl_clean_up;
}
lbl_clean_up:
{
if(res1 != NULL)
free(res1);
if(res2 != NULL)
free(res2);
if(res3 != NULL)
free(res3);
return;
}
现在我应该使用样式1还是样式2?样式2具有更多冗余的if语句,但在我看来看起来更具可读性。
仅在需要时进行优化。如果您的代码在没有优化代码的情况下运行良好,则优先考虑可读性。
我希望使用第二种方法的变体。使用goto
跳转到清理代码是一种处理事情的干净方法。
为了改善这一点,在空指针上调用free
是无操作的,因此不需要额外的if
:
void foo(void)
{
void* res1 = NULL, *res2 = NULL, *res3 = NULL;
res1 = malloc(1);
if(res1 == NULL)
goto lbl_clean_up; //operation failed
res2 = malloc(1);
if(res2 == NULL)
{
goto lbl_clean_up;
}
res3 = malloc(1);
if(res3 == NULL)
{
goto lbl_clean_up;
}
lbl_clean_up:
free(res3);
free(res2);
free(res1);
return;
}
也是按照分配资源的相反顺序释放资源的一种好习惯。在使用多个标签时,可以进一步使用它。例如:
void foo(void)
{
FILE *f1, *f2, *f3;
f1 = fopen("infile1", "r");
if (f1 == NULL)
goto cleanup1;
f2 = fopen("infile2", "r");
if (f2 == NULL)
goto cleanup2;
f3 = fopen("outfile", "w");
if (f3 == NULL)
goto cleanup3;
// do something
close(f3);
cleanup3:
close(f2);
cleanup2:
close(f1);
cleanup1:
return;
}
在malloc失败的情况下,速度差异无关紧要。
样式1有一个更严重的问题:多重回报。这样的函数(IMO)更加难以阅读,更改函数返回类型也更加困难]