在C++中为什么要或不要使用memset?

6

我需要维护一个程序,里面有很多memset。在现代C++中使用memset是一个好的实践吗?

为什么?或者为什么不?

如果不是,那么应该优先考虑什么替代方法?


1
请使用 std::fill,它可以在可能的情况下优化为 memset 并且可用于类。 - Neil Kirk
1
如果您将数据类型定义为类,则构造函数可以负责初始化。但是,如果您将其视为原始内存字节,则memset是更好的选择。 - Dr. Debasish Jana
@NPE 你能举个例子说明memset适用而fill不适用的情况吗? - Neil Kirk
@NeilKirkпјҡиҷҪ然fill()жҳҜйҰ–йҖүпјҢдҪҶжҲ‘зӣёдҝЎеңЁжҹҗдәӣжғ…еҶөдёӢmemset()еҸҜиғҪжӣҙдјҳгҖӮиҝҷйҮҢжҳҜжҲ‘еҝ«йҖҹжҗңзҙўеҲ°зҡ„дёҖдёӘдҫӢеӯҗпјҡhttps://dev59.com/questions/H2445IYBdhLWcg3wBl2J - NPE
@NeilKirk:刚意识到我的措辞有点模糊。 "yes/no/maybe" 部分是回答使用 memset() 是否是良好实践的问题,而不是回答是否有更好的方法的问题。 - NPE
2个回答

14

90%的情况下,您应该使用std::fill而不是memset。这是因为std::fill可以正确处理类,并且在将非字节类型的数组设置为非零值时也可以正常工作。例如,您可以将一个int数组的值memset为0,但不能将其值memset为0x12345678。但是,使用std::fill就可以做到。

好的编译器可以将std::fill优化为适当的memset。在它们不这样做的情况下,任何性能影响都可能是微不足道的。

在memset应该使用std::fill的情况下,使用std::fill并不危险。但是,在应该使用std::fill的情况下使用memset是危险的。默认使用std::fill

对于memcpystd::copy同样适用。


1
你还有10%的时间该怎么做呢?使用memset。那么,在什么情况下应该使用memset而不是std::fill呢? - Z boson
3
我不知道,我只是这样做是为了防止有人提出一些奇怪的边缘情况,在这种情况下memset比fill更好。 - Neil Kirk

3
显然,memset() 只有可能适用于标准布局类型。即使对于这些类型,其值也不一定可预测。例如,没有保证空指针将具有所有空字节,尽管我不知道任何不使用所有空字节的空指针的系统。
显而易见的替代方法是使用构造函数。对于非标准布局类型,使用构造函数显然是正确初始化对象的唯一方法。即使对于 POD 类型,也有生成适当零初始化的构造函数。也就是说,构造函数通常不会初始化任何填充,而 memset() 将初始化填充。此外,调用构造函数涉及开销:如果需要初始化多个对象,则使用 memset() 更加高效。在我编写的代码中,我并不经常遇到需要批量初始化许多对象的情况,即对我来说性能论点并不存在。
个人而言,我不会使用 memset() 初始化对象,而是使用生成的构造函数。要初始化对象序列,我要么依赖容器完成工作,要么使用适当的 fill()uninitialized_fill()。在很少情况下,我看到频繁使用 memset() 来初始化对象,这总是错误的,即我认为使用 memset() 是一个警告信号,尽管它可以正确使用。
因此,总之,我认为这是不良的实践,而是采用一致的方法使用适当的构造函数,可能是从容器中或在必要时(例如,当实现类似于 std::vector<T> 的东西时)使用合适的算法。如果性能表明它实际上有所不同,并且正在初始化的对象是标准布局类型,则可能会选择 memset(),但我不知道,因为我从未遇到过必须初始化许多标准布局(或 POD)类型的情况。

4
有没有任何一个在七秒钟内给这个回答点了踩的用户想要评论一下?你真的读那么快吗? - Neil Kirk
我意识到我没有给出期望的答案(“memset()很棒 - 就用它吧”),但我仍然对这个踩票的原因感兴趣。 - Dietmar Kühl
你很好地讨论了构建对象的情况,但如果你有一些现有的对象并想给它们赋新值呢? - Neil Kirk
@NeilKirk 更有可能的是,他是那些投票关闭此问题并认为这已足以对回答进行负面评价的人之一。我会点赞。 - Iwillnotexist Idonotexist
@NeilKirk:确实如此,尽管我认为很明显的方法是使用适当的赋值,可能通过std::fill()std::fill_n()来完成,如果它是一个序列而不是memset() - Dietmar Kühl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接