c++ - memcpy 的类型安全 C++ 包装器?

标签 c++ memcpy

鉴于std::copy (显然对于普通类型)只能实现为 memmove 的包装器(*),我想知道:

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

(*):C++ 标准库实现(从 MSVC 2005(!) 到现代 MSVC2015、libc++ 等)衰减 std::copy TriviallyCopyable 类型到 memmove。机器人memcpy。因为:

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

    The behavior is undefined if d_first is within the range [first, last).

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

    If the objects overlap, the behavior is undefined.

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

    The objects may overlap: copying takes place as if the characters were copied to a temporary character array and then the characters were copied from the array to dest.

    • 即源和目的范围可以任意重叠,没有限制。

鉴于此,很明显您可以使用 std::memove 为 TrivialllyCopyable 类型实现 std::copy,因为 memmove 不施加任何限制并且可以在编译时通过类型特征分派(dispatch)到正确的实现 --

但很难根据 memcpy 实现 std::copy,因为 (a) 检查指针范围是否重叠必须在 运行时,以及 (b) 甚至对不相关的内存范围实现运行时检查 could be quite a mess .

所以,这给我们留下了

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

一个接口(interface)不太出色的函数,您经常需要将非字符对象的输入计数与其 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。

那么我真的必须自己重新发明这个轮子吗?是否讨论过标准?等等


最佳答案

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

对象可能会重叠:复制过程就像将字符复制到临时字符数组,然后将字符从数组复制到目标。

Is there a Standard C++ type-safe wrapper for the times you need memcpy? (I can't count the number of times I forgot to multiply by sizeof.)

是的,std::copy(也许,在下面解释)

If there's nothing in the standard, have there been any proposals for this? If not, why not?

据我所知,该标准不强制对普通类型的 std::copy 使用 memmove/memcpy。因此,该执行了。例如在 visual studio update 2015 update 2 they did use memmove to speed things up :

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

Are there any specific obstacles in providing a memcpy wrapper that does the sizeof multiplication automatically?

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

编辑:

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

Complexity: Exactly last - first assignments.

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

关于c++ - memcpy 的类型安全 C++ 包装器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42720353/

相关文章:

c++ - 当代码在 Visual Studio C++ 中正常工作时出现 MSB6006 错误

c++ - 为什么map.find使用<运算符而不是==运算符?

c - memcpy vs 用于读取 BLE 传感器 float 的指针转换

c - 取消引用 C 中的函数指针以访问 CODE 内存

c - 使用 memcpy 避免陷阱表示

c++ - std::errc,如何在 retval 中指示成功

c# - 旧 C++ 应用程序和新 C# 应用程序之间的桥梁

c++ - 使用 boost::spirit::x3 从 std::string 解析为 boost::string_view

c++ - 将结构复制(使用赋值)到 union 内的结构导致段错误

c++ - 使用reinterpret_cast 转换二进制数据在char数组中的偏移量