下面的删除声明是代码冗余。
int *a = new int[100]
if (!doSomething1(a))
delete[] a
return
if (!doSomething2(a))
delete[] a
return
if (!doSomething3(a))
delete[] a
return
return
我想出的另一个选择是:
if(doSomething1(a) || doSomething2(a) || doSomething3(a))
;
delete[] a;
return;
但它不适合我想添加指定给doSomething1()的指令的情况,例如
if(!doSomething1(a))
foo;
delete[] a;
return;
if(!doSomething2(a))
delete[] a;
return;
我被告知至少有5种方法可以减少这种代码冗余。那么有什么建议吗?
更新,还有一个问题: 同样的问题,让我们将域限制为C,注意流程逻辑的变化。
char *a = (char*)malloc(100*sizeof(char));
if(doSomething1(a))
foo;
free(a)
return;
if(doSomething2(a))
free(a)
return;
if(doSomething3(a))
free(a);
return;
free(a);
return
答案 0 :(得分:2)
为什么需要手动删除任何内容?这是C ++,所以我们可以使用析构函数和RAII。
std::vector<a>(100);
if (!doSomething1(a))
return;
if (!doSomething2(a))
return;
if (!doSomething3(a))
return;
更一般地说:如果在离开范围时需要发生任何事情,那么在该范围内的自动对象的析构函数中进行。
但为什么使用返回值表示失败?这是C ++,所以我们可以使用例外:
std::vector<a>(100);
doSomething1(a);
doSomething2(a);
doSomething3(a);
答案 1 :(得分:1)
“RAII”和“范围退出”将是Google或SO的良好搜索字词。例如,请查看Boost.ScopeExit或alternatives to it。我们的想法是创建一个本地对象并将其留给析构函数来进行清理或“最终”代码。
这是尝试将这个成语直接应用到你的例子中,减少到最低限度(没有错误检查和类似的东西):
class AutomaticDeleter
{
public:
AutomaticDeleter(int *a) : a(a) {}
~AutomaticDeleter() { delete[] a; }
int *GetWrappedPointer() const { return a; }
private:
int *a;
};
// ...
AutomaticDeleter automatic_deleter(new int[100]);
if (!doSomething1(automatic_deleter.GetWrappedPointer()))
return;
if (!doSomething2(automatic_deleter.GetWrappedPointer()))
return;
if (!doSomething3(automatic_deleter.GetWrappedPointer()))
return;
当然,我应该提一下,这只是可以所做的事情的一个例子,而不是你将应用于指针时应该做什么的一个例子,特别是从new[]
返回的人。在现实生活中,你使用std::vector<int>
并完成它。这个成语有更多有趣和有用的应用程序。
答案 2 :(得分:0)
do {
if (doSomething1(a) && doSomething2(a) && doSomething3(a)){
break; /*all good: move outside the dummy loop*/
}
/*one of the functions failed*/
delete[] a;
return;
} while (false);
是一种方式。我依赖于if
严格从左到右评估语句的事实,并且一旦达到false
就会停止评估。
(这个习惯用法在C中经常使用;请参阅unix内核源代码)。
答案 3 :(得分:0)
bool failure;
int *a = new int[100]
if ( failure = !doSomething1(a))
//...
if ( !failure && ( failure = !doSomething2(a) ) )
//...
if ( !failure && ( failure =!doSomething3(a) ) )
//...
if ( failure )
{
delete []a;
return;
}
//,,,
return