提问人:kingsjester 提问时间:11/17/2023 最后编辑:kingsjester 更新时间:11/17/2023 访问量:156
std::copy、std::equal、std::fill 相对于 memcpy、memset、memcmp 的实际优势
Practical advantages of std::copy, std::equal, std::fill over memcpy, memset, memcmp
问:
一些帖子比较了 C++ 风格函数和 C 风格函数之间的性能,例如:std::copy, std::equal, std::fill
std::memcpy, std::memcmp, std::memset
但是,从实用的角度来看,我还没有找到用这些新功能替换旧函数的合理性。当然,功能列表并非详尽无遗。
这些新版本的实际优势是什么?
如果性能不是选择的标准,那么是否希望(在时间允许的情况下)用 C++ 版本替换这些 C 样式函数的所有出现?
我试图理解为什么引入了一些功能,以及是否有必要进行替换。c++
答:
memset
有两个巨大的局限性。
首先是容器。对于使用连续内存的容器,只能使用多个元素。它可以适用于大多数其他容器,但不适用于大多数其他容器。memset
std::array
std::vector
接下来是元素。您只能简单地复制对象。已经是“简单”的东西,因为不能轻易复制。memset
std::string
memset
在某些情况下可以使用。您提到的其他函数更普遍适用,当它们可以被编译器替换时可以做到这一点。memset
评论
std::copy
memset
std::copy
std::memcpy
正如评论中所指出的,等工作,其中如,等。仅在极少数情况下有效。特别是,不适用于任何具有非平凡构造函数的东西,因此不适用于任何标准容器。即使在 C 样式或 s 的 C 样式数组上使用时,它也只能进行浅层复制,因此根据对象的语义,它甚至可能不适用于包含指针的 C 样式。std::copy
std::memcpy
std::memcpy
struct
struct
struct
关于性能,当然没有什么是可以保证的。但是编译器可以访问 的源代码(因为它是一个模板),并且通常能够内联它——对于 C 样式,这通常会导致复制更大的块(机器字,而不是字节)。在 的情况下,通常会有一个函数调用,它隐藏了有关底层上下文的任何信息,并且需要逐字节复制(导致循环中的次数更多),或者需要处理对齐和可能的奇数字节的复杂逻辑。C标准确实允许成为一个宏,解析为一个特殊的符号,触发某种编译器优化,但我认为这在C++中是不合法的。一些早期的(C)标准C编译器确实将其识别为关键字,以便生成内联代码。但这一切都是很久以前的事了(在第一个 C 标准之前)。std::copy
struct
std::memcpy
memcpy
memcpy
在今天的 C++ 代码中,绝对没有理由使用 ,永远。std::memcpy
评论
memcpy
memcpy
-O0
/O2
g++ -S -O3
cl /c /O2 /Fa
memcpy
memcpy
memcpy
memcpy
memcpy
std::copy
std::memcpy
std::copy
但是,从实用的角度来看,我还没有找到用这些新功能替换旧函数的合理性。
这些函数更通用。 并且仅针对 TriviallyCopyable 的连续类型范围定义,并且(通常)仅对没有填充的 TriviallyCopyable 类型的连续范围有意义。注意,单个物体是长度为1的连续范围。memcpy
memset
memcmp
只有当它们执行相同的操作时,性能才具有可比性,并且根据假设规则,实现可以选择以完全相同的方式实现对的调用,就像它可以证明范围不重叠或其他方式时一样。与 1 类似。std::copy
memcpy
memmove
std::fill
memset
std::equal
memcmp
- 稍作修改,因为它不在乎少或多,只在乎相等
评论
char
memset
int
1
memset
std::fill
memcmp