鉴于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/