我们正在一个平台上开发应用程序,该平台的编译器不支持C ++语言中的异常。
当我们调用API时,我们需要检查返回结果中的错误代码。有时我们需要在发生错误时进行一些清理。我们定义一个宏CHECK_ERROR_GOTO来检查错误代码。所以像这样的代码。
int res = callAPI1();
CHECK_ERROR_GOTO(res, cleanup);
A* object1 = callAPI2(); // HERE WE WILL GET ERROR,
//BECAUSE GOTO SKIP INITIALIZATION OF OBJECT1
CHECK_ERROR_GOTO(object1 == NULL, cleanup);
C* object2 = callAPI3(object2);
CHECK_ERROR_GOTO(object2 == NULL, cleanup)
return 0;
cleanup:
//Cleanup code here.
delete object1
delete object2
如代码所示,我们将通过goto跳过初始化的object1,因此我们需要在函数的头部放置object1
和object2
,这很糟糕,因为我们应该把它放在我们的位置需要使用。并且添加{}来创建局部作用域不起作用,因为清理代码需要使用局部变量。
所以无论如何我们可以安排代码,所以我们不需要在函数的开头放置变量初始化吗?
答案 0 :(得分:2)
您说您的编译器不支持异常。但它是否支持在早期返回时执行析构函数?我当然希望它能做到。你应该通过一个简单的测试来确保。
这意味着您可以使用智能指针和其他在析构函数中释放资源的类。
int res = callAPI1();
if (!res) return -1;
scoped_ptr<A> object1(callAPI2());
if (!object1) return -1;
scoped_ptr<C> object2(callAPI3(object1.get()));
if ((!object2) return -1;
return 0;
scoped_ptr
这里可以是任何合适的智能指针类:你的编译器unique_ptr
在不太可能的情况下是支持它,auto_ptr
如果你感到勇敢,boost::scoped_ptr
如果
template <typename T>
class scoped_ptr {
T* raw;
struct bool_dummy { void fn() {} };
typedef void (bool_dummy::*pseudo_bool)();
scoped_ptr(const scoped_ptr&); // non-copyable
scoped_ptr& operator =(const scoped_ptr&);
public:
scoped_ptr(T* raw) : raw(raw) {}
~scoped_ptr() { delete raw; }
T* get() const { return raw; }
T& operator *() const { return *get(); }
T* operator ->() const { return get(); }
operator pseudo_bool() const { return get() ? &bool_dummy::fn : 0; }
bool operator !() const { return !get(); }
};
答案 1 :(得分:0)
我喜欢这样做:
int foo()
{
A* object1 = 0; // make sure you initialize those two
C* object2 = 0; // so that further delete calls always work
for (;;)
{
int res = callAPI1();
if (res == -1)
break;
object1 = callAPI2();
if (object1 == 0)
break;
object2 = callAPI3(object1);
if (object2 == 0)
break;
return 0;
}
delete object1;
delete object2;
return -1;
}
然而,并不总是可以像上面那样清楚地表达代码。但是当它发生时,我发现它很棒。它的优点是可以在一个地方放置(就像一个goto
)清理代码。否则它可能变得不可维护,如:
// don't do this:
if(object2==0)
{
delete object1;
return 0;
}
// ... more code ...
if(object3==0)
{
delete object2;
delete object1;
return 0;
}
// ... more code ...
if(object4==0)
{
delete object3
delete object2;
delete object1;
return 0;
}
答案 2 :(得分:0)
是的,不是最美丽的代码,但它会:
int res = callAPI1();
if (!res) /* inverse of CHECK_ERROR_GOTO(res, cleanup); ??? */
{
A * object1 = callAPI2();
if (object1 != null) /* inverse of CHECK_ERROR_GOTO(object1 == NULL, cleanup); */
{
C * object2 = callAPI3(object1); //I suppose you want object1 here and not 2
if (object2 != null) /* inverse of CHECK_ERROR_GOTO(object2 == NULL, cleanup);*/
{
/* if we reached here then both object1 and 2 are created
thus delete both before returning to not get any memory leaks */
delete object1;
delete object2;
return 0;
}
/* if we reached here then the creation of object2 has failed.
Only delete object1 because object2 is not initialized. */
delete object1;
/* do some kind of return here? like -3 */
}
/* do some kind of return here? like -2 */
}
/* do some kind of return here? like -1*/