我正在寻找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_backward
和copy_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>
答案 0 :(得分:3)
安全*。为什么?因为标准并没有说不安全 。他们复制25.3.1中的函数需要:以获取他们需要的东西(这是其他复制形式中重叠禁止的地方)。
但是,copy_n
不表示它要求范围不重叠,这意味着它没有问题,因为它没有明确禁止。如果它需要它,它会说明它。
*编辑:当我的意思是'#34;安全&#34;我的意思是它没有未定义的行为或不合格的程序。但是,如果内存范围重叠,则结果不能保证是您可能想要的结果。我们唯一保证的是:
i < n
,执行*(result + i) = *(first + i)
因此,我们可以推断,如果范围重叠,则存储在目的地的结果不再保证是源的精确(有序)副本。我们保证目标中的每个值都来自源,但确切的值取决于重叠和元素复制的确切顺序。
所以如果通过&#34; safe&#34;你的意思是目的地总是有一个完美的来源副本(如memmove
),然后不,它不是&#34;安全&#34;。但它在某种意义上是安全的,它本身不会导致未定义/无效的行为。
总结一下,我们保证将为整个范围内的每个元素完成*(result + i) = *(first + i)
。我们保证如果范围重叠,程序仍然没有定义。我们无法保证复制元素的顺序。我们无法保证如果范围重叠,结果中存储的确切值将是多少(但我们知道它们都来自源)。
答案 1 :(得分:1)
我同意Cornstalks的回答,并且同意+1。但是,理论必须得到实践的支持。
快速浏览一下GCC(libstdc ++ - v3)和Clang(libc ++)的实现,可以看出他们的copy_n
与copy
相同(或代表)memmove
,不支持重叠将对象移动到更高的地址。
所以,MSVC赢了这一轮,至少在代表{{1}}的POD案例中胜出。