我已经看到在 memmove 和 memcpy 之间有什么区别?它说memmove might be very slightly slower than memcpy
。
我们可以通过以下方式实现替代方案memmove
:分配一个临时缓冲区,然后分配memcpy
两次(src -> tmp,tmp -> dest)。我的问题是:哪种方式更快,memmove
还是另一种方式?
我已经看到在 memmove 和 memcpy 之间有什么区别?它说memmove might be very slightly slower than memcpy
。
我们可以通过以下方式实现替代方案memmove
:分配一个临时缓冲区,然后分配memcpy
两次(src -> tmp,tmp -> dest)。我的问题是:哪种方式更快,memmove
还是另一种方式?
来自http://en.cppreference.com/w/cpp/string/byte/memmove
尽管指定“好像”使用临时缓冲区,但此函数的实际实现不会产生双重复制或额外内存的开销。对于小计数,它可能会加载和写出寄存器;对于较大的块,一种常见的方法(glibc 和 bsd libc)是如果目标在源之前开始,则从缓冲区的开头向前复制字节,否则从结尾向后复制,当有时回退到 std::memcpy根本没有重叠。
因此,开销很可能是几个条件分支。对于大块来说几乎不值得担心。
然而,值得记住的是,这std::memcpy
是一个“魔法”函数,是在两种不同类型之间进行转换的唯一合法方式。
在 c++ 中,这是非法的(未定义的行为):
union {
float a;
int b;
} u;
u.a = 10.0;
int x = u.b;
这是合法的:
float a = 10.0;
int b;
std::memcpy(std::addressof(b), std::addressof(a), size(b));
如果你是一个 C 程序员,你会做你期望工会做的事情。
std::memmove
“可能比”(强调)慢一点,std::memcpy
因为它必须首先检查源范围和目标范围是否重叠。在内部,这只是几个指针比较;完成后,如果没有重叠或目标从源下方开始,它会调用std::memcpy
; std::memcpy
否则,它会从结尾向开头调用该副本的变体。
简而言之,唯一的区别是初始比较;一旦完成,就像std::memcpy
. 不需要额外的缓冲区并将所有内容复制两次。
Memcpy 通常更快,因为它不认为目标和源可以重叠。
因此,如果您尝试使用 memcpy 将字符串abcd
从某个位置复制X
到X+2
,则可能会得到这样的结果
X: A B C D
在 memcpy 之后
X+2 A B A A
而 memmove 将向您保证不会丢失任何内容,因为它使用中间缓冲区来存储原始字符串。
另一方面,您可以restrict
对源和目标使用限定符,这样您可以告诉 memmove 源和目标不重叠,并且如果您使用此限定符,memmove 可以选择其他更快的算法。
有关详细信息,请参见此处。