我有一个STL容器,我需要对容器中的每个元素执行一个操作.但是如果操作在任何元素上失败,我想要反转已经更改过的任何元素的操作.
例如,如果我有一个STL向量,指向一个数字bankAccount类,并希望每个增加50美元.但是,如果任何银行账户的失败由50增加,我想50 $任何已增加了账户的完全和减少取消的增加.
std::vector<bankAccount*> bankAccounts;
std::vector<bankAccount*>::iterator iter;
for (iter = bankAccounts.begin(); iter != bankAccounts.end(); ++iter)
{
try
{
iter->increaseBalance(50);
}
catch (...)
{
// One of the bankAccounts failed to increase by 50, now I need to go
// back and decrease by 50 all of the bankAccounts that have already
// been increased.
}
}
Run Code Online (Sandbox Code Playgroud)
有没有优雅的方法来做到这一点?也许使用STL算法或使用反向迭代器?
这就是我要做的事情:
bankAccounts容器的副本increaseBalance每个项目swap()原始和重复容器代码看起来像这样:
std::vector<bankAccount> bankAccounts;
...
std::vector<bankAccount> tmp(bankAccounts);
try
{
for (iter = tmp.begin(); iter != tmp.end(); ++iter)
{
iter->increaseBalance(50);
}
bankAccounts.swap(tmp);
}
catch (...)
{
}
Run Code Online (Sandbox Code Playgroud)
请注意,持有指向a内部对象的指针std::vector通常不是一个好主意,因为容器期望存储在其中的数据具有值语义,而不是指针语义.这可能导致悬空指针,内存泄漏,还需要额外的清理代码,否则您不需要(手动删除容器中的项目).使用上面的代码,我已经切换到将数据保存在向量中,如果这不是一个选项,则需要确保在复制向量时使用手动深层复制.
实际上,如果您对bankAccounts和使用相同的定义,则可以将代码减少到以下内容tmp:
std::for_each(tmp.begin(), tmp.end(),
std::mem_fun_ref(&bankAccount::increaseBalance, 50));
bankAccounts.swap(tmp);
Run Code Online (Sandbox Code Playgroud)
上述代码的主要优点是,在这两种情况下,它都是异常安全的,没有任何进一步的特殊处理.