std :: copy_n是否与重叠范围一起工作?

时间:2013-12-23 05:03:03

标签: c++ algorithm stl stl-algorithm

我正在寻找N3485 25.3.1 [alg.copy]的C ++标准,该标准定义了4种算法:

  • copy
  • copy_backward
  • copy_if
  • copy_n

copy的说明中,有一条注释25.3.1 [alg.copy] / 3:

  

要求:结果不应在[first,last]范围内

也就是说,copy在范围重叠时并不总能正常工作(类似于memcpy)。

copy_backwardcopy_if有类似的语言禁止重叠范围(分别为25.3.1 [alg.copy] / 14和25.3.1 [alg.copy] / 8)。

但是,copy_n没有此类禁令,并且没有copy_n_backward。这是否意味着copy_n在范围重叠时做正确的事情?

(MSVC ++的copy_n实现似乎委托给std::memmove,所以我知道它在MSVC ++ 2013上是安全的。但是如果标准暗示的话,我不想依赖它<) / p>

2 个答案:

答案 0 :(得分:3)

安全*。为什么?因为标准并没有说不安全 。他们复制25.3.1中的函数需要:以获取他们需要的东西(这是其他复制形式中重叠禁止的地方)。

但是,copy_n 表示它要求范围不重叠,这意味着它没有问题,因为它没有明确禁止。如果它需要它,它会说明它。

*编辑:当我的意思是'#34;安全&#34;我的意思是它没有未定义的行为或不合格的程序。但是,如果内存范围重叠,则结果不能保证是您可能想要的结果。我们唯一保证的是:

  1. 对于每个非负整数i < n,执行*(result + i) = *(first + i)
  2. 不禁止调用具有重叠范围的函数,并且不会导致未定义的行为。
  3. 因此,我们可以推断,如果范围重叠,则存储在目的地的结果不再保证是源的精确(有序)副本。我们保证目标中的每个值都来自源,但确切的值取决于重叠和元素复制的确切顺序。

    所以如果通过&#34; safe&#34;你的意思是目的地总是有一个完美的来源副本(如memmove),然后不,它不是&#34;安全&#34;。但它在某种意义上是安全的,它本身不会导致未定义/无效的行为。

    总结一下,我们保证将为整个范围内的每个元素完成*(result + i) = *(first + i)。我们保证如果范围重叠,程序仍然没有定义。我们无法保证复制元素的顺序。我们无法保证如果范围重叠,结果中存储的确切值将是多少(但我们知道它们都来自源)。

答案 1 :(得分:1)

我同意Cornstalks的回答,并且同意+1。但是,理论必须得到实践的支持。

快速浏览一下GCC(libstdc ++ - v3)和Clang(libc ++)的实现,可以看出他们的copy_ncopy相同(或代表)memmove,不支持重叠将对象移动到更高的地址。

所以,MSVC赢了这一轮,至少在代表{{1}}的POD案例中胜出。