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