【发布时间】:2012-04-12 04:06:58
【问题描述】:
强大的异常安全保证表明,如果发生异常,操作不会改变任何程序状态。实现异常安全复制分配的一种优雅方式是copy-and-swap idiom。
我的问题是:
对更改非原始类型的类的每个变异操作使用复制和交换会不会过大?
对于强大的异常安全来说,性能真的是公平交易吗?
例如:
class A
{
public:
void increment()
{
// Copy
A tmp(*this);
// Perform throwing operations on the copy
++(tmp.x);
tmp.x.crazyStuff();
// Now that the operation is done sans exceptions,
// change program state
swap(tmp);
}
int setSomeProperty(int q)
{
A tmp(*this);
tmp.y.setProperty("q", q);
int rc = tmp.x.otherCrazyStuff();
swap(tmp);
return rc;
}
//
// And many others similarly
//
void swap(const A &a)
{
// Non-throwing swap
}
private:
SomeClass x;
OtherClass y;
};
【问题讨论】:
-
答案很大程度上取决于您的域,并且无法在域之外回答。如果生命依赖于它,答案是显而易见的:它值得付出性能代价。如果异常处理代码会在发生异常时破坏您的对象,那也没关系。现在你必须找到你的代码在中间的位置。
-
如果您将代码正确地分解为单一职责组件,您通常会“免费”获得很多异常安全性。在您的示例中,为什么“增量”函数会做“疯狂的事情”?要么增量算法很复杂并且知道如何以事务方式进行计算,要么你需要将增量和疯狂填充分开。
-
好吧,您可以使用相同的想法并将其应用于成员。不需要是全部。如果说你的类包含一个字符串向量,你只需要改变一个怎么办?不要复制/交换整个类、向量和所有内容。只需在一个字符串上执行即可。
-
旁注:在开始在任何地方使用它们之前,请确保您确实需要异常。见this question
标签: c++ exception-safety