std::copy\n是否适用于重叠范围? 我在C++标准中查看N348 525.3.1 [Alg.Reopy],定义了4种算法: 复制 向后复制 如果 copy\n

std::copy\n是否适用于重叠范围? 我在C++标准中查看N348 525.3.1 [Alg.Reopy],定义了4种算法: 复制 向后复制 如果 copy\n,c++,algorithm,stl,stl-algorithm,C++,Algorithm,Stl,Stl Algorithm,在复制的说明中,有以下注释25.3.1[alg.复制]/3: 要求:结果不应在[第一,最后]范围内 也就是说,当范围重叠时,copy并不总是正常工作(类似于memcpy) copy_backward和copy_if具有禁止重叠范围的类似语言(分别为25.3.1[alg.copy]/14和25.3.1[alg.copy]/8) 但是,没有禁止copy\n,也没有copy\n\u backward。这是否意味着copy\n在范围重叠时做正确的事情 (MSVC++的copy\n实现似乎委托给了std:

复制的说明中,有以下注释25.3.1[alg.复制]/3:

要求:结果不应在[第一,最后]范围内

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

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

但是,没有禁止
copy\n
,也没有
copy\n\u backward
。这是否意味着
copy\n
在范围重叠时做正确的事情


(MSVC++的
copy\n
实现似乎委托给了
std::memmove
,因此我知道在MSVC++2013上它是安全的。但如果标准另有规定,我不想依赖它)

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

但是,
copy\n
并没有说它要求范围不重叠,这意味着它可以,因为它没有明确禁止。如果它需要,它会声明它

*编辑:当我指的是“安全”时,我的意思是这样做不是未定义的行为或错误的程序。但是,如果内存范围重叠,结果不能保证是您可能想要的。我们唯一能保证的是:

  • 对于每个非负整数
    i
    ,执行
    *(结果+i)=*(第一个+i)
  • 调用具有重叠范围的函数是不被禁止的,并且不会导致未定义的行为
  • 因此,我们可以推断,如果范围重叠,则存储在目标中的结果不再保证是精确的(按顺序)源文件的副本。我们保证目标文件中的每一个值都来自源文件,尽管这些值的精确性取决于重叠和元素的精确复制顺序

    因此,如果“安全”是指目标始终具有源代码的完美副本(如
    memmove
    ),那么不,它不是“安全”的。但它是安全的,因为它本身不会导致未定义/无效的行为


    总而言之,我们保证
    *(result+i)=*(first+i)
    将对整个范围内的每个元素执行。我们保证,如果范围重叠,程序仍然没有定义。我们不保证复制元素的顺序。我们不保证如果范围重叠,结果中存储的确切值将是什么(但我们确实知道它们都来自源头)。

    我同意玉米秸秆的答案,而且+1。但是,理论必须得到实践的支持

    快速浏览一下GCC(libstdc++-v3)和Clang(libc++)的实现,可以发现它们的
    copy\n
    copy
    相同(或委托给
    copy
    ),在将对象移动到更高的地址时不支持重叠


    因此,MSVC赢得了这一轮,至少在POD案例中,授权给
    memmove

    当迭代器不支持随机访问时,
    copy\n
    如何进行安全检查?(它只需要一个输入迭代器和一个输出迭代器……)@Billy cplusplus.com说,
    如果范围重叠,result指向的范围中的某些元素可能有未定义但有效的值。
    但我不知道这有多可靠。@remyabel:cplusplus.com==非常不可靠。@BillyONeal:Updated。对不起,我最初的意思是“安全”与您可能使用的不同。因此允许传递重叠范围,但实际上这样做会产生不可预测的结果,因此在任何可能的情况下都是无用的?多么奇怪的规范。为什么不将其与其他
    复制
    函数一样对待?它们可能在想什么?(我同意规范似乎是这么说的,所以+1。但这太奇怪了。)“MSVC++对
    copy\n
    的实现似乎委托给了
    std::memmove
    ”请注意,我们只在这种转换正确的情况下才这样做;也就是说,迭代器是指向可复制对象的指针。@James:当然。:)在这种情况下,这恰好是一个安全的转换。@James:啊,我明白你的意思。如果输入是例如
    std::list
    iterators,那么在MSVC++的实现中是不安全的。听起来像是对我的回答……哇,这是一个奇怪的边缘情况,我想说这可能是个错误(他们打算这样做)但它似乎几乎是故意被忽略了……原始版本确实对
    复制有这样的要求。我不知道为什么这不在标准中。你可以提交一个问题。顺便说一句,
    复制
    只禁止输出从输入范围开始的重叠,但在输出范围结束时,它可以正常工作(即复制到左侧)。