【问题标题】:C++ STL's copy() exception safetyC++ STL 的 copy() 异常安全
【发布时间】:2015-03-12 17:47:15
【问题描述】:

如果我这样做了

std::copy(source, source + size, destination);

我有强大的异常安全保证吗? IE。如果 std::copy 抛出,destination 保持不变?

【问题讨论】:

  • 请回复参考。
  • 怎么可能?最终它必须开始接触目的地,如果在目的地中途停止工作,则会处于不一致的状态。
  • 想一想 10 秒钟。唯一可能的方法是在复制之前备份目标。即使有可能,这也是一个糟糕的想法至少有以下原因:(1)它需要分配额外的内存,(2)它会很慢,(3)复制(备份)以及恢复(从备份)很容易抛出另一个异常,就像原来的抛出异常一样。

标签: c++ exception stl


【解决方案1】:

附录 E:标准库异常安全来自 Stroustrop 的C++ 编程语言freely viewable from his website

由此而来:

copy() 算法(第 18.6.1 节)提供强大的 异常安全保证。它不保证如果出现异常,它将保持其目标不变 复制过程中抛出

【讨论】:

    【解决方案2】:

    来自标准:

    25.3.1 复制 [alg.copy]

    template<class InputIterator, class OutputIterator>
       OutputIterator copy(InputIterator first, InputIterator last,
                           OutputIterator result);
    

    1 效果:[first,last) 范围内的元素复制到[result,result + (last -first)) 范围内,从first 开始,一直到last。对于每个非负整数n &lt; (last -first),执行*(result + n) = *(first + n)

    2 返回: result + (last - first).

    3 要求: result 不得在 [first,last) 范围内。

    4 复杂性: 完全是last - first 分配。

    它不对异常安全做出任何保证。它也没有指定result[first,last) 范围内时的行为。

    【讨论】:

    • 它不必与每个算法一起列出,之前可能有一个涵盖一组算法的一般性声明。无论如何,提供强大的异常保证的真正问题是 T.C.在这个答案中说 - 如果 result 是只写输出迭代器,则无法 回滚 到原始内容。
    • 即使您可以回滚,也不应该尝试。如果这引发 second 异常怎么办?!
    【解决方案3】:

    快速搜索第 25 条(指定大多数标准算法的条款)表明没有短语 no effects 的实例,并且该标准将强异常安全性指定为“如果抛出异常(有/功能有)没有效果”。换句话说,第 25 条中的任何内容都没有强有力的异常安全保证。

    另外,std::copy 怎么可能提供强大的异常安全保证呢? dest 可以是不一定可读的任意输出迭代器,并且可以在写入时执行任意操作。如果是std::ostream_iterator 怎么办?如何“取消写入”已写入流的内容?

    【讨论】:

      【解决方案4】:

      副本在 25.3.1 中定义为

      template<class InputIterator, class OutputIterator>
      OutputIterator copy(InputIterator first, InputIterator last,
      OutputIterator result);
      1 Effects: Copies elements in the range [first,last) into the range [result,result + (last -
      first)) starting from first and proceeding to last. For each non-negative integer n < (last -
      first), performs *(result + n) = *(first + n).
      2 Returns: result + (last - first).
      3 Requires: result shall not be in the range [first,last).
      4 Complexity: Exactly last - first assignments.
      

      可以有效地写成:

      template<class InputIterator, class OutputIterator>
        OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
      {
        while (first!=last) {
          *result = *first;
          ++result; ++first;
        }
        return result;
      }
      

      如果在第一次执行循环后的任何时间发生异常,那么它的格式化方式将改变目标。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        相关资源
        最近更新 更多