Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

Vinllen Chen


To be a better coder

memcpy, memmove和copy/copy_if/copy_n/copy_backward的区别

  在C++中有多种方式可以进行数据拷贝,但它们实现的方式略有不同。

memcpy

  memcpy原型如下,其以字节为单位,可以用来拷贝非重合区域。也就是说如果拷贝的源、目的有重合部分的话,结果是undefined,意味着可能偶尔也是对的。但最好不要这么做,原则上memcpy是一种后向拷贝机制:从区间的最后一个元素开始进行拷贝,直到第一个元素。

void* memcpy( void* dest, const void* src, std::size_t count );  

memmove

  memmove可以支持重合区域的拷贝,其实现可以理解为memmove用另外一块buffer缓存src数据,然后往dst拷贝。但实际上并不是这样,代码在输入时会进行判断:如果src地址小于dst地址,进行后向拷贝;反之如果src地址大于dst,进行前向拷贝。这样就完美的避开了拷贝区间重复而覆盖的问题。

void* memmove( void* dest, const void* src, std::size_t count );  

copy/copy_if/copy_n/copy_backward

  copy系列函数大部分是C++11支持的模板。原则上是支持重合区域的拷贝,但是是一种『未定义但有效』的方式(undefined but valid),也就是说结果『通常』都是对的,由编译器去实现具体细节,所以不同编译器可能行为上不一致。前面三个都是前向拷贝,最后一个是后向拷贝。也就是说,使用者需要自己去定义:什么时候使用前向拷贝,什么时候使用后向拷贝(参考memmove)。

copy

  以下是官网给出的可能的实现机制,从代码实现来说不支持重复区域。

template<class InputIt, class OutputIt>  
OutputIt copy(InputIt first, InputIt last,  
              OutputIt d_first)
{
    while (first != last) {
        *d_first++ = *first++;
    }
    return d_first;
}

  泛型如下(C++11)

template< class InputIt, class OutputIt >  
OutputIt copy( InputIt first, InputIt last, OutputIt d_first );  

copy_n

template<class InputIterator, class Size, class OutputIterator>  
  OutputIterator copy_n (InputIterator first, Size n, OutputIterator result)
{
  while (n>0) {
    *result = *first;
    ++result; ++first;
    --n;
  }
  return result;
}
template< class InputIt, class Size, class OutputIt >  
OutputIt copy_n( InputIt first, Size count, OutputIt result );  

copy_if

template<class InputIt, class OutputIt, class UnaryPredicate>  
OutputIt copy_if(InputIt first, InputIt last,  
                 OutputIt d_first, UnaryPredicate pred)
{
    while (first != last) {
        if (pred(*first))
            *d_first++ = *first;
        first++;
    }
    return d_first;
}
template< class InputIt, class OutputIt, class UnaryPredicate >  
OutputIt copy_if( InputIt first, InputIt last,  
                  OutputIt d_first,
                  UnaryPredicate pred );

copy_backward

  后向拷贝:

template< class BidirIt1, class BidirIt2 >  
BidirIt2 copy_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last)  
{
    while (first != last) {
        *(--d_last) = *(--last);
    }
    return d_last;
}
template< class BidirIt1, class BidirIt2 >  
BidirIt2 copy_backward( BidirIt1 first, BidirIt1 last, BidirIt2 d_last );  

参考

http://www.cplusplus.com/reference/algorithm/copy_n/
http://en.cppreference.com/w/cpp/string/byte/memmove
http://en.cppreference.com/w/cpp/string/byte/memcpy
http://en.cppreference.com/w/cpp/algorithm/copy
http://en.cppreference.com/w/cpp/algorithm/copy_backward
http://stackoverflow.com/questions/41425865/how-to-move-2-elements-from-head-into-given-position-in-vector

说明

装载请注明出处:http://vinllen.com/memcpy-memmovehe-copy-copyif-copyn-copy_backwardde-qu-bie/


About the author

vinllen chen

Beijing, China

格物致知


Discussions

comments powered by Disqus