memcpy的Type-Safe C ++包装器?

时间:2017-03-10 14:09:56

标签: c++ memcpy

鉴于std::copy(显然是琐事类型)只能作为memmove(*)的包装器实现,我想知道:

  • 您需要memcpy时是否有标准的C ++类型安全包装器? (我无法计算我忘记乘以sizeof的次数。)
  • 如果标准中没有任何内容,是否有任何建议?如果没有,为什么不呢?
  • 提供自动memcpy倍增的sizeof包装器是否存在任何特定障碍?

(*):C ++标准库实现(从MSVC 2005(!)到现代MSVC2015,libc ++等)将std::copy TriviallyCopyable类型衰减到memmove。 Bot memcpy。这是因为:

  • std::copy(src_first, src_last, destination_first)定义:

      

    如果d_first[first, last)范围内,则行为未定义。

    • 只有目标范围的开头不得在目标范围内。目标范围允许扩展到目标范围。也就是说,d_first可以在左边"源范围,目标范围可以扩展到源范围。
  • 对于std::memcpy,定义是

      

    如果对象重叠,则行为未定义。

    • 也就是说,完整范围不能重叠:这是允许memcpy成为最快变体的原因,因为它可以假设源和目标的内存是完全不相交的。
  • 对于std::memmove,定义为:

      

    对象可能重叠:复制就像将字符复制到临时字符数组一样,然后将字符从数组复制到dest。

    • 也就是说,源和目标范围可以任意重叠,没有限制。

鉴于此,很明显您可以使用std::memove为TrivialllyCopyable类型实现std::copy,因为memmove不会施加任何限制,并且可以在以下位置完成对正确实现的调度。通过类型特征编译时间 -

但是很难用std::copy来实现memcpy因为(a)检查指针范围是否重叠必须在运行时完成 >,和(b)甚至对不相关的内存范围could be quite a mess执行运行时检查。

所以,这给我们留下了

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

一个接口少于恒星的函数,你经常需要将非char对象的输入计数与它们的sizeof相乘,这是完全无类型的。

但memcpy是最快的(并且相当大的余地,自己测量),当你需要TriviallyCopyable类型的快速拷贝时,你可以达到memcpy。其中表面应该很容易包装在类型安全的包装中,如:

template<typename T>
T* trivial_copy(T* dest, T* src, std::size_t n) {
    return static_cast<T*>(std::memcpy(dest, src, sizeof(T) * n));
}

但是,你不清楚你应该通过std::is_trival或某些人进行编译时间检查,当然可能会讨论是否采用确切的memcpy签名顺序,yadda yadda。

所以我真的必须自己重新发明这个轮子吗?它是否针对该标准进行了讨论?等

1 个答案:

答案 0 :(得分:1)

根据docs澄清mencpy和memove之间的区别 memmove可以将内存复制到与源内存重叠的位置,对于memcpy,这是未定义的行为。

对象可能重叠:复制就像将字符复制到临时字符数组一样,然后将字符从数组复制到dest。

  

在需要memcpy时,是否有标准的C ++类型安全包装器? (我无法计算我忘记乘以sizeof的次数。)

是的,std :: copy(可能,如下所述)

  

如果标准中没有任何内容,是否有任何建议?如果没有,为什么不呢?

据我所知,该标准没有为std :: copy强制使用memmove / memcpy来处理普通类型。所以这是实施。例如,在visual studio update 2015 update 2 they did use memmove to speed things up中:

提高了std :: vector重新分配和std :: copy()的速度;它们的速度提高了9倍,因为它们为简单的可复制类型(包括用户定义的类型)调用了memmove()

  

提供自动执行sizeof乘法的memcpy包装器是否存在任何特定障碍?

不,实际上您可以使用std::is_trivial

自行实现

编辑:

根据this document第25.3.1节,对std :: copy实现只有复杂性没有限制:

  

复杂性:完全持续 - 第一次任务。

当你认为memcpy使用cpu特定指令(在所有cpus上都不可用)来加速内存复制时,这是非常有意义的。