Search code examples
c++memset

memset and a dynamic array of std::complex<double>


since std::complex is a non-trivial type, compiling the following with GCC 8.1.1

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

produces a warning

clearing an object of non-trivial type

My question is, is there actually any potential harm in doing so?


Solution

  • The behavior of std::memset is only defined if the pointer it is modifying is a pointer to a TriviallyCopyable type. std::complex is guaranteed to be a LiteralType, but, as far as I can tell, it isn't guaranteed to be TriviallyCopyable, meaning that std::memset(z, 0, ...) is not portable.

    That said, std::complex has an array-compatibility guarantee, which states that the storage of a std::complex<T> is exactly two consecutive Ts and can be reinterpreted as such. This seems to suggest that std::memset is actually fine, since it would be accessing through this array-oriented access. It may also imply that std::complex<double> is TriviallyCopyable, but I am unable to determine that.

    If you wish to do this, I would suggest being on the safe side and static_asserting that std::complex<double> is TriviallyCopyable:

    static_assert(std::is_trivially_copyable<std::complex<double>>::value);
    

    If that assertion holds, then you are guaranteed that the memset is safe.


    In either case, it would be safe to use std::fill:

    std::fill(z, z + 6, std::complex<double>{});
    

    It optimizes down to a call to memset, albeit with a few more instructions before it. I would recommend using std::fill unless your benchmarking and profiling showed that those few extra instructions are causing problems.