【发布时间】:2010-09-23 05:30:01
【问题描述】:
由于 C++ you have to use the RAII 设计模式中没有 finally,因此如果您希望代码是异常安全的。一种方法是使用本地类的析构函数,如下所示:
void foo() {
struct Finally {
~Finally() { /* cleanup code */ }
} finalizer();
// ...code that might throw an exception...
}
与直接解决方案相比,这是一个很大的优势,因为您不必编写 2 次清理代码:
try {
// ...code that might throw an exception...
// cleanup code (no exception)
} catch (...) {
// cleanup code (exception)
throw;
}
本地类解决方案的一大缺点是您无法在清理代码中直接访问本地变量。因此,如果您需要访问它们,它将使您的代码膨胀很多:
void foo() {
Task* task;
while (task = nextTask()) {
task->status = running;
struct Finally {
Task* task;
Finally(Task* task) : task(task) {}
~Finally() { task->status = idle; }
} finalizer(task);
// ...code that might throw an exception...
}
}
所以我的问题是: 有没有结合这两种优势的解决方案?这样您 a) 不必编写重复的代码 b) 可以访问清理代码中的局部变量,如上一个示例中的 task,但不会出现这种代码膨胀。
【问题讨论】:
-
那是丑陋的。你应该创建一个 RunObject 什么的!!!
-
+1 提出这个问题,因为经常看到不熟悉
RAII的人认为finally很好...... -
“您不必编写 2 次清理代码”。为什么你会写两次代码,出于某种原因?这就是 =P Neutral 在 RAII 与 finally 问题上的子例程,但是编写两次代码是一个红鲱鱼:您可以创建一个清理例程,将任务传递给它,然后在两个地方调用它。无需重复代码。在您的简单示例中,这在逻辑上是任务析构函数的一部分。但是,如果出于某种原因需要在 foo 中进行清理,则在此处创建一个本地清理例程。
标签: c++ exception finally c++-faq