memset和std :: complex <double>的动态数组

时间:2018-08-02 16:09:47

标签: c++ memset

由于std :: complex是非平凡的类型,请使用GCC 8.1.1编译以下内容

complex<double>* z = new complex<double>[6];
memset(z,0,6*sizeof*z);
delete [] (z);`

发出警告

  

清除非平凡类型的对象

我的问题是,这样做实际上有潜在的危害吗?

3 个答案:

答案 0 :(得分:4)

仅在std::memset的行为是指向TriviallyCopyable类型的指针时才定义其行为。 std::complex被保证为 LiteralType ,但据我所知,它不能保证为 TriviallyCopyable ,这意味着{{1} }不可移植。

也就是说,std::memset(z, 0, ...)有一个array-compatibility guarantee,它表示std::complex的存储正好是两个连续的std::complex<T>,可以照此重新解释。这似乎表明T实际上很好,因为它将通过这种面向数组的访问进行访问。这也可能暗示std::memset 可完全复制的,但我无法确定。

如果您希望这样做,建议您保持安全,并std::complex<double>声明static_assert TriviallyCopyable

std::complex<double>

如果该断言成立,那么可以保证static_assert(std::is_trivially_copyable<std::complex<double>>::value); 是安全的。


在两种情况下,都可以使用memset

std::fill

optimizes down是对std::fill(z, z + 6, std::complex<double>{}); 的调用,尽管之前还有一些其他说明。我建议使用memset,除非您的基准测试和性能分析表明这几条额外的说明会引起问题。

答案 1 :(得分:1)

永远,永远,永远memset个非POD类型。他们有一个构造器。仅在它们上面写入一堆字节是不太可能给出期望结果的(如果确实如此,则类型本身设计不良,因为它们应该清楚地放在首位,否则它们应该是POD -否则,您很不幸在这种情况下,未定义行为似乎可以工作-在更改优化级别,编译器或平台(或月相)后,如果没有进行调试,请尝试调试它。 >

请不要这样做。

答案 2 :(得分:0)

这个问题的答案是,对于符合标准的wordToken "the man saw." > ["the", "man", "saw", "."] ,在std::complex之后不需要memset

new将复数初始化为new complex<double>[6],因为它调用了初始化为零的默认(非平凡)构造函数。 (不幸的是,我认为这是一个错误。) https://en.cppreference.com/w/cpp/numeric/complex/complex

如果发布的代码是公正的,并且示例在(0, 0)new之间缺少代码,那么memset将做正确的事情。 (部分原因是特定的标准库实现内部了解std::fill的实现方式。)