memcpy的内存重叠问题 + memcpy比for循环效率高

通常来说,这个函数的实现比较简单

我看了下crt的实现源码,如下:(略去64位机的)

void * __cdecl memcpy (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;
 
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }
 
        return(ret);
}

今天,我看到一个面试题上叫实现这个函数,看了下它的参考答案,如下

void *MyMemCopy(void *dest,const void *src,size_t count)
{
    char *pDest=static_cast<char *>(dest);
    const char *pSrc=static_cast<const char *>(src);
 
    //注意,这里是关键,为什么要这样比较呢?理由何在?
    if( pDest>pSrc && pDest<pSrc+count )
    {
        for(size_t i=count-1; i>=0; ++i)
        {
            pDest[i]=pSrc[i];
        }
    }
    else
    {
        for(size_t i=0; i<count; ++i)
        {
             pDest[i]=pSrc[i];
        }
    }
 
    return pDest;
}

这其实是为了解决区域重叠问题

比如这种

|              src           |
            |         dst            |


memcpy跟memmove的区别,memmove可以处理重叠的情况

来源:http://bbs.csdn.net/topics/210050580


另外,用一个for循环去复制一块内存永远比memcpy慢,因为memcpy是编写CRT库的人手工写出的为CPU特别优化的汇编代码(另一个原因是大多数编译器会特殊处理memcpy这个函数)。——见《游戏之旅——我的编程感悟》82页

在古老的介绍优化的书本上,很多前辈提到过循环展开这样的优化策略,也就是说,通过减少循环的次数,而在循环体内复制多次需要做的事物可以减少操作循环计数器的次数,以此来提高一点运行速度。我本人是不赞同这种方案的,即使真的能提高速度,这样做也破坏了程序美感。到了Pentium时代,循环展开更是画蛇添足的败笔,因为他极大地影响了CPU内部缓存的工作。

——见184页

你可能感兴趣的:(效率)