我有一些看起来像这样的代码:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes = DoSomething1(a, b, c); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } iRes = DoSomething2(a, c, e); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } ... iRes = DoSomething10(c, d, e); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } clean1(a, b, c); clean2(d, e); return 0; }
如何在C或C ++中避免重复if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; }
if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; }
每个函数调用后?
笔记:
例:
这段代码是这种情况的一个例子:每10行代码实际上= 2行仅用于实际执行 + 8行错误测试和清理……我们能做得更好吗?
正如贾斯汀所说,答案将根据语言的不同而有所不同。
如果你在C,这是goto
在语言中有一个据点的最后一个地方。 例如,如果您有:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes = DoSomething1(a, b, c); if (iRes > 0) { goto error_cleanup; } iRes = DoSomething2(a, c, e); if (iRes > 0) { goto error_cleanup; } /*...*/ iRes = DoSomething10(c, d, e); if (iRes > 0) { goto error_cleanup; } /* SUCCESS */ clean1(a, b, c); clean2(d, e); return 0; /* ERROR EXIT POINT */ error_cleanup: clean1(a, b, c); clean2(d, e); log_error(); return 1; }
但是,在C ++中,我们需要处理这个清理代码,即使抛出exception,这也会使事情变得更加棘手。 但是,在c ++中我们也有RAII,这意味着析构函数是可行的方法。
这是我喜欢的一个技巧,避免了goto:
bool success = false; do { r = do_something(); if (r) break; r = do_something_else(); if (r) break; r = do_something_again(); if (r) break; success = true; } while(0); if (! success) { clean_up(); }
对于给定的代码,您可以使用以下任何一种变体:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } clean1(a, b, c); clean2(d, e); return 0; }
如果在clean1()
和clean2()
之前或之后clean1()
clean2()
,可以使用:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { log_error(); } clean1(a, b, c); clean2(d, e); return 0; }
甚至:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { // Don't need to do anything here } clean1(a, b, c); clean2(d, e); if (iRes > 0) log_error(); return 0; }
if
的主体可能是最终的任务:
int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... ) { iRes = DoSomething10(c, d, e); } clean1(a, b, c); clean2(d, e); if (iRes > 0) log_error(); return 0; }
这种重构取决于清理在所有情况下都是相同的。 通常,它不是那么系统化。 由于您没有显示a
, b
, c
, d
或e
中的任何a
被初始化,因此很难确定什么是真正安全的。 如果doSomethingN()
函数在C ++中并通过引用获取参数,则doSomething1()
可以初始化a
, b
, c
– 但是在d
或e
具有值之前可能会发生对clean2()
的调用。
以上就是c/c++开发分享模式避免“如果清理失败”重复相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/550074.html