memmove vs向后复制

时间:2014-03-03 21:40:33

标签: c++ c copy memmove

我知道C(cstring库)中的memmove可以很好地处理重叠“,代价是运行速度较慢”(参见this post)。我想知道为什么这个额外的运行时成本?在我看来,任何重叠问题都可以通过向后复制而不是向前复制来解决,我错了吗?

作为玩具示例,这里有两个版本的“右移”功能,它将数组的内容移动右侧的一个元素:

// Using memmove
template <typename T>
void shift_right( T *data, unsigned n )
{
    if (n)
    {
        data[n-1].~T();
        memmove( data+1, data, (n-1)*sizeof(T) );
        new (data) T();
    }
}

// Using copy_backward
template <typename Iterator>
void shift_right( Iterator first, Iterator last )
{
    Iterator it = last;
    std::copy_backward( first, --it, last );
}

他们是等同的吗?性能方面,哪一个最好用?


注意:根据@DieterLücking的评论判断,尽管采取了预防措施,但在这种情况下使用memmove的上述版本是不安全的。

4 个答案:

答案 0 :(得分:6)

假设一个好的实现,memmove的唯一“额外成本”是初始检查(添加和比较和分支),以决定是从前到后还是从后到后复制面前。这个成本是完全可以忽略的(添加和比较将被ILP隐藏,并且分支在正常情况下是完全可预测的),在某些平台上,memcpy只是memmove的别名。

预期你的下一个问题(“如果memcpy没有明显快于memmove,为什么它存在?”),有一些很好的理由可以保持memcpy。在我看来,最好的一个是,一些CPU实际上将memcpy实现为单个指令(例如,在x86上为rep/movs)。这些HW实现通常具有优选(快速)操作方向(或者它们可能仅支持在一个方向上的复制)。编译器可以用最快的指令序列自由替换memcpy,而不必担心这些细节;它不能对memmove执行相同的操作。

答案 1 :(得分:2)

Memmove告诉你是否要向后或向前复制;它也针对此任务进行了高度优化(即尽可能多地在SSE优化块中进行复制)。

你不可能通过调用任何通用的STL算法做得更好(他们能做的最好的事情就是在幕后调用memcopy或memmove),但当然你只需运行你的代码和时间就可以回答这个问题。它

答案 2 :(得分:2)

来自您实际链接的帖子(强调我的):

  

memcpy只是循环,而memmove执行测试来确定哪个   循环方向以避免破坏数据。这些   实现相当简单。最高性能   实现更复杂(涉及复制字大小   一次阻止而不是字节。)

答案 3 :(得分:2)

复制或移动的适当方法是std :: copy,std :: copy_n,std :: copy_backward和std :: move。如果适用,正确的C ++库将使用memcpy或memmove。因此,如果复制或移动的序列不存在重要数据,则无需进行未定义的结果。

注意:这里std :: move是模板'OutputIterator move(首先是InputIterator,最后是InputIterator,OutputIterator结果);' (对于@Void)