看了STL关于copy函数的实现,从效率实现真的做到了极致,其中,当拷贝区间的元素有trivial assignment operator(也就是平凡的赋值操作符),为了提高效率,使用内存直接复制行为(mommove或momcpy函数)。这里简单记录下,以备忘。。

0. mommove或momcpy函数都是c语言中的库函数,作用都是一样的,原型如下:

void *memcpy(void *dst, const void *src, size_t n);  
void *memmove(void *dst, const void *src, size_t n); 

都是用来复制src所指内存的前n个字节到dst内存区域中,返回的都是指向dst的指针,但是区别是当内存放生局部重叠时,memmove保证结果正确,memcpy不保证拷贝结果正确,原因会在下面解释。

1.首先关于cpoy会出现以下几种情况:如图:<主要是针对输入和输出区间是同一个区间>

第一种:将输入区间的元素拷贝到输出区间的红色区点域的位置,也就是输出区间的尾部与输入区间发生重叠,也就是dst <= src的情况,这种情况拷贝结果是正确的。

第二种:将输入区间的元素拷贝到输出区间的黑色点区域的位置,也就是输入区间和输出区间完全没有重叠,也就是(char*)dst >= (char*)src + n 的情况,这种情况拷贝结果是正确的

第三种:将输入区间的元素拷贝到输出区间的绿色点区域的位置,也就是输出区间的头部与输入区间发生重叠,也就是dst > src && (char*)dst < (char*)src + n   的情况,这种情况拷贝结果会出现问题,因为复制输入区间前,它的元素值可能被覆盖,这种情况memmove函数值这样处理的:反向进行复制,也就是src和dst的尾部成了头部,而头部成了尾部,dst = (char*)dst + n - 1;src = (char*)src + n - 1;然后从右向左复制就变成第一种情况,这种会保证复制结果是正确的。

2. memcpy和memmove源码:

 

void* memcpy(void* dst, const void* src, size_t n)
{
    if (NULL == dst || NULL == src)
        return NULL;
    void* ret = dst;
    char *dst_ = (char*)dst;
    char *src_ = (char*)src;
    while (n--)                                   
    {
        *dst_++ = *src_++;
    }
    return ret;
}

void* memmove(void* dst, const void* src, size_t n)
{
    if (NULL == dst || NULL == src)
        return NULL;
    void* ret = dst;                                   
    char *dst_=(char*)dst;
    char *src_=(char*)src;
    if (dst <= src ||dst_ >= (src_ + n))  //第一种和第二种的情况
    {
        while (n--)                                    //正向进行复制(从头至尾)
        {
          *dst_++=*src_++;   
        }
    }
    else                              //第三种情况             反向进行复制(从尾至头)
    {
        dst_ += n - 1;
        src_ += n - 1;
        while (n--)
        {
           *dst_ -- =*src_ --;
        }
    }
   return ret;
 }

 

posted on 2017-07-04 20:49  liuamin  阅读(1186)  评论(0编辑  收藏  举报