为啥或为啥不在 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
。
memcpy
和 std::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? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 CDC::LineTo() 不在 Visual C++ 2015 MFC 对话框中绘制?