这是我对memmove的实现;我可以在哪里改进呢?
void* memmove(void* dest, const void* src, std::size_t count)
{
char *dest_ = static_cast<char*>(dest), *src_ = (char*)(src);
if ((char*)src + count > dest && src < dest) //
{
dest_ += (src_ += count - 1, count - 1);
while (count--) *dest_-- = *src_--;
}
else while (count--) *dest_++ = *src_++;
return dest;
}发布于 2017-09-06 11:01:02
缺少标头:#include <cstddef>是std::size_t所必需的(其他标头也提供它)。
src_没有必要抛弃*src的稳定性:
char *dest_ = static_cast<char*>(dest);
char const *src_ = static_cast<char const*>(src);就我个人而言,我只想选择d和s,而不是那些丑陋的下划线,但这在很大程度上是品味的问题。
在指向不同对象的指针之间使用<进行算术和比较是未指定的行为;我们可以安全地使用std::less。或者我们可以接受未指定的结果,因为在src和dest位于不同对象的情况下,使用哪个分支并不重要。
没有必要测试src + count > dest和src < dest;只要在分支中不减去count==0,我们就可以很高兴地为任何低到高的副本使用“反向”副本。
在“反向”分支中,将分配给src_的任务隐藏在分配给dest_的内部是不诚实的。写成两句话要清楚得多:
src_ += count - 1;
dest_ += count - 1;我们可以避免-1,如果我们在减少之前,而不是后减少(它是安全的指向一个过了尾声)。
风格:在else的两边使用大括号,或者两者都不使用;避免使用if () {} else ;。
#include <cstddef>
void *memmove(void *dest, const void *src, std::size_t count)
{
auto d = static_cast<char*>(dest);
auto s = static_cast<char const*>(src);
// If s and d are in distinct objects, the comparison is
// unspecified behaviour, but either branch will work.
if (s < d) {
s += count;
d += count;
while (count--)
*--d = *--s;
} else {
while (count--)
*d++ = *s++;
}
return dest;
}一次复制一个字符将是一种“懒散”。真正的实现利用了处理器的本地传输大小、DMA硬件和可用的专用指令。这就是为什么它是一个标准的库函数而不是用户提供的。
发布于 2017-09-06 10:45:16
将指针与无关对象有未指定的结果进行比较。
不要使用C风格的转换,也不要在任何地方一致使用它们.相反,使用static_cast<char*>(const_cast<void*>(src))。
不要在单个语句(dest_ += ...)中使用多个赋值,特别是不要与逗号运算符结合使用。这只会让人感到困惑,对人类读者和编译器都没有帮助。
删除空注释。它没有任何用途。
与添加count - 1不同,您可以添加count并使用预减量。这是更清晰的代码,因为你周围没有魔法1。
条件下的强制转换可以由src_代替。
整个条件应该读取(src_ < dest_ && dest_ < src_ + count),以匹配测试之间的通用模式。
https://codereview.stackexchange.com/questions/174935
复制相似问题