用于memcpy的类型安全C 包装器

Type-Safe C++ wrapper for memcpy?

本文关键字:包装 类型安全 memcpy 用于      更新时间:2023-10-16

鉴于std::copy(显然对于琐碎类型)只能作为MEMMOVE周围的包装器实现(*),我想知道:

  • 您需要memcpy时有标准的C 类型安全包装器吗?(我无法计算我忘记乘以sizeof的次数。)
  • 如果标准中没有任何建议,对此有任何建议吗?如果不是,为什么不呢?
  • 提供memcpy乘法的CC_4包装器有什么特定的障碍?

(*):C 标准库实现(从Back MSVC 2005(!)到Modern MSVC2015,libc 等)衰减std::copy可腾出的类型到memmove。bot 不是 to memcpy。因为:

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

    如果d_first[first, last)范围内,则行为是不确定的。

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

    如果对象重叠,则行为是不确定的。

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

    对象可能重叠:复制发生,好像字符被复制到临时字符数组,然后将字符从数组复制到dest。

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

给出了这一点,很明显,您可以使用std::memove来实现std::copy用于琐事类型,因为MEMMOVE不会施加任何限制,并且可以通过类型特征在编译时完成对正确实现的派遣 -

但是,很难以memcpy来实现std::copy无关的内存范围可能很混乱。

所以,这使我们有

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

一个函数少于恒星接口,在其中您不断地需要将非char对象的输入计数与其sizeof相乘,并且完全没有构图。

但是,memcpy是最快的(并且要有很大的边距,请自己进行测量),当您需要快速的琐碎类型的快速副本时,您就可以找到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。

那么,我真的必须自己重新发明这条轮子吗?是为标准讨论的吗?等。


根据文档的说明memmove可以将内存复制到与源内存重叠的位置,对于memcpy,这是未定义的行为。

" 对象可能会重叠:复制发生,好像字符被复制到临时字符数组,然后将字符从数组复制到dest。

您需要Memcpy时有标准的C 类型安全包装器吗?(我无法计算我忘记乘以大小的次数。)

是,std ::复制(也许在下面解释)

如果标准中没有任何建议,对此有任何建议吗?如果不是,为什么不呢?

据我所知,标准并未强制使用sTD ::副本的memmove/memcpy使用。因此,这是实施的。例如,在Visual Studio Update 2015 Update 2中,他们确实使用MemMove加快了速度:

" 提高了std :: vector Realocation和std :: copy()的速度;当他们调用MemMove())时,它们的速度更快到9倍(包括用户定义类型)(包括用户定义的类型)。"

提供一个自动乘法大小的记忆包装器有什么特定的障碍?

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

自己实现此功能

编辑:

根据本文档第25.3.1节,对STD没有限制::复制实现仅复杂性:

复杂性:最后 - 首次分配。

当您考虑Memcpy使用CPU特定指令(所有CPU上的CPU)来加快内存副本时,这是非常有道理的。