• Copy (C标准函数mommove和momcpy)<一>


    看了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;
     }
  • 相关阅读:
    Java中equals和==的区别
    Golang 中的 defer 关键字
    浅拷贝与深拷贝
    svn 忽略某些文件夹或者文件类型
    使用 nvm 管理 nodejs 版本
    数据库索引
    解决 vscode 安装 golang 环境出现 connection failed 的情况
    TSQL 如何批量修改/转移大数据量数据.
    从别人那儿陶的一个配置文件处理方法.
    分析sqlserver查询计划
  • 原文地址:https://www.cnblogs.com/liuamin/p/7115845.html
Copyright © 2020-2023  润新知