zoukankan      html  css  js  c++  java
  • 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;
     }
  • 相关阅读:
    windows服务的默认启动类型和登录帐户
    oracle通过sql随机取表中的10条记录
    oracle如何四舍五入?
    Sql Server数据库自增长字段标识列的插入或更新修改操作办法
    将一个表中的数据导入到另一张表中
    设计模式已经陨落了?
    LINQ架构简单描述
    Asp.Net 验证控件
    .Net 三层架构开发初步
    C++编程思想
  • 原文地址:https://www.cnblogs.com/liuamin/p/7115845.html
Copyright © 2011-2022 走看看