向前迭代然后反转STL容器

时间:2010-07-15 18:49:08

标签: c++ stl

我有一个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.
    }
}

有没有优雅的方法来做到这一点?也许使用STL算法或使用反向迭代器?

2 个答案:

答案 0 :(得分:9)

这就是我要做的事情:

  • 将try / catch移到循环外
  • 创建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 (...)
{
}

请注意,持有指向std::vector内对象的指针通常不是一个好主意,因为容器期望存储在其中的数据具有值语义,而不是指针语义。这可能导致悬空指针,内存泄漏,还需要额外的清理代码,否则您不需要(手动删除容器中的项目)。使用上面的代码,我已经切换到将数据保存在向量中,如果这不是一个选项,则需要确保在复制向量时使用手动深层复制。

实际上,如果您对bankAccountstmp采用相同的定义,则可以将代码缩减为以下内容:

std::for_each(tmp.begin(), tmp.end(),
              std::mem_fun_ref(&bankAccount::increaseBalance, 50));
bankAccounts.swap(tmp);

上述代码的主要优点是,在这两种情况下,如果没有任何进一步的特殊处理,它是异常安全的。

答案 1 :(得分:1)

我认为更优雅的方法是将操作视为交易。换句话说,创建帐户的替换副本,并在成功时覆盖原始文档。