Search code examples
c++complex-numbers

c++ replace memset with std::fill


Hello I'm trying to port some old code to new standards. I have a

std::complex<double> **data_2D;

And I need to set a portion of that to zero. I used to do with:

memset( &( data_2D[dims[0]-delta][0] ), 0, delta*dims[1]*sizeof( std::complex<double> ) );

which gives this warning:

clearing an object of non-trivial type 'class std::complex<double>'; use assignment or value-initialization instead

How do I change that memset with a std::fill ? I got lost in double pointers...

Here is a minimale example:

#include <iostream>
#include <complex>
#include <string.h>

int main() {
    unsigned int dims[2]={10,10};

    std::complex<double> *cdata_ = new std::complex<double>[dims[0]*dims[1]];
    std::complex<double> **data_2D;
    
    data_2D= new std::complex<double> *[dims[0]];
    for( unsigned int i=0; i<dims[0]; i++ ) {
        data_2D[i] = cdata_ + i*dims[1];
        for( unsigned int j=0; j<dims[1]; j++ ) {
            data_2D[i][j] = 0.0;
        }
    }
    
    unsigned int delta=5;
    memmove( &( data_2D[0][0] ), &( data_2D[delta][0] ), ( dims[1]*dims[0]-delta*dims[1] )*sizeof( std::complex<double> ) );
    memset( &( data_2D[dims[0]-delta][0] ), 0, delta*dims[1]*sizeof( std::complex<double> ) );
    
    return 0;
}

Solution

  • You don't need to change anything about the pointers. If you use std::fill_n you only need to be careful of the arguments being in a different order and that the number of elements, not the number of bytes, is expected:

    std::fill_n( &( data_2D[dims[0]-delta][0] ), delta*dims[1], 0 );
    

    However, &...[0] has the same effect as implicit array-to-pointer decay, so it can be written as well as

    std::fill_n( data_2D[dims[0]-delta], delta*dims[1], 0 );
    

    And I don't really see the point in having data_2D in the first place. Just index cdata_ directly:

    std::fill_n( cdata_ + (dims[0]-delta)*dims[1], delta*dims[1], 0 );
    

    Or if you want an interface to index by row and column, wrap cdata_ in a class with a member function indexing the array by 2D indices.

    I would also recommend replacing new if you are already modernizing. It should be a std::vector instead.