为啥或为啥不在 C++ 中使用 memset? [关闭]

Posted

技术标签:

【中文标题】为啥或为啥不在 C++ 中使用 memset? [关闭]【英文标题】:Why or why not use memset in C++? [closed]为什么或为什么不在 C++ 中使用 memset? [关闭] 【发布时间】:2014-10-04 18:40:49 【问题描述】:

我必须维护一个程序中有很多 memset。在现代 C++ 中使用 memset 是一种好习惯吗?

为什么,为什么不呢?

如果不是,什么比 memset 更受欢迎?

【问题讨论】:

没有。请改用std::fill。它可以在可能的情况下优化为 memset,并且可以与类一起使用。 如果您将数据类型定义为类,那么构造函数可能会负责初始化。但是,如果您将其视为原始内存字节,那么 memset 是选择 @NPE 你能举一个例子说明 memset 可以在哪里工作,而 fill 不能工作吗? @NeilKirk:虽然fill() 是首选,但我确信在某些极端情况下memset() 在某些方面更胜一筹。这是我通过快速搜索找到的:***.com/questions/5074208/… @NeilKirk:刚刚意识到我的措辞有点模棱两可。 “是/否/可能”位是针对使用memset() 是否是好的做法,而不是针对是否有首选方法。 【参考方案1】:

90% 的时间你应该使用std::fill 而不是 memset。这是因为std::fill 可以在类中正常工作,并且在将非字节类型的数组设置为非零值时也可以正常工作。例如,您可以将整数数组 memset 为 0,但不能将整数数组 memset 为 0x12345678。使用std::fill 即可。

好的编译器可以将std::fill 优化为合适的memset。在他们不这样做的情况下,任何性能影响都可能可以忽略不计。

当 memset 更快时使用 std::fill 并不危险。在应该使用 std::fill 的地方使用 memset 是危险的。默认为std::fill

memcpystd::copy 同上

【讨论】:

剩下的 10% 的时间你应该做什么?使用memset。如果是这样,您应该在什么情况下使用memset 而不是std::fill @Zboson 我不知道,我只是把它放在我的后背上,以防有人想出一些奇怪的边缘情况,在这种情况下 memset 比 fill 更好。【参考方案2】:

显然,memset() 只能与标准布局类型一起使用。即使对于那些值也不一定是可预测的。例如,虽然我不知道空指针不使用所有空字节的任何系统,但不能保证空指针将具有所有空字节。

显而易见的替代方法是使用构造函数。对于非标准布局类型,使用构造函数显然是正确初始化对象的唯一方法。即使对于 POD 类型,也有生成适当的零初始化的构造函数。也就是说,构造函数通常不会初始化任何填充,而 memset() 会初始化填充。此外,调用构造函数会产生开销:如果需要初始化许多对象,使用memset() 可能更有效。在我编写的代码中,我并没有真正遇到需要批量初始化许多对象的情况,即性能参数对我来说并不存在。

就个人而言,我不会使用memset() 初始化对象,而是使用生成构造函数。为了初始化对象序列,我要么依靠容器来完成这项工作,要么依靠fill()uninitialized_fill() 的适当使用。在我看到频繁使用memset() 来初始化对象的少数情况下,它总是错误的,即我认为使用memset() 是一个警告标志,尽管它可以正确使用。

因此,总而言之,我认为这是不好的做法,而是使用一致的方法,即使用合适的构造函数,可能来自容器内,或者在必要时(例如,在实现类似于 std::vector<T> 的合适算法时。如果性能表明它实际上有所作为,并且正在初始化的对象是标准布局类型可能memset() 可能是一个选择,但我不知道,因为我从未遇到过最终不得不初始化大量标准布局的情况(或 POD)类型。

【讨论】:

在 7 秒内否决了这个答案的用户有什么评论吗?你真的读得那么快吗? 我意识到我没有给出想要的答案(“memset() 很棒 - 去吧”)但无论如何我都会对投票的原因感兴趣。 你很好地讨论了构造对象的情况,但是如果你有一些现有的对象并想给它们一个新的值呢? @NeilKirk 更有可能他是投票结束这个问题的人之一,并认为这足以让他对这个问题的答案投反对票。我赞成。 @NeilKirk: true 虽然我认为很明显该方法是使用适当的分配,可能通过std::fill()std::fill_n() 如果它是一个序列而不是@ 987654334@.

以上是关于为啥或为啥不在 C++ 中使用 memset? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 memset() 放在循环体内时不能正常工作?

为啥 memset 在苹果 clang 编译器中工作错误?

为啥memset不能将数组元素初始化为1?(急)

为啥 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制?

为啥可以从 QWidget 创建一个对象而不在 C++ 程序的开头包含它

为啥在 memset 中使用 '\0' 而不是 0?