鉴于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
,定义是
如果对象重叠,则行为未定义。
对于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。
所以我真的必须自己重新发明这个轮子吗?它是否针对该标准进行了讨论?等
答案 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上都不可用)来加速内存复制时,这是非常有意义的。