Storing 3D Array on Heap as Structure Member

Viewed 116

I recently started working with C++ for numerical computations where I want to use a Struct Operators to store 3D Fields over the course of the simulation. I create the 3D arrays on the heap with

const unsigned int RES = 256;
auto arr3D = new double [RES][RES][RES];

because from what I've tested this approach is faster than using either Boost_multiarr, Eigen Tensor or nested Vectors. So far this worked fine with my minimalistic Test.cpp but when I try to implement these same 3D Arrays as Members of my Struct Operators, I cannot use the auto command anymore:

const unsigned int RES = 256;

struct Operators {
public:
    std::complex<double>*** wfc;         // edited, see 'spitconsumers' comment

    Operators(Settings &set) {        // just another structure used by Operators
        wfc = new std::complex<double> [RES][RES][RES];

        // ...Initializing wfc using Settings

};

In this case I found no way of declaring wfc, such that I do not get errors of the type

error: cannot convert 'std::complex (*)[256][256]' to 'std::complex***' in assignment

So my question is how to correctly declare the 3D Array wfc and whether maintaining this Structure approach is at all possible/useful. Would it generally be faster to access the wfc[i][j][k] if wfc was not member of a structure? (I will have to do this ~10^6 times)

Thanks in advance!

2 Answers

In your error message, the compiler is telling you that new complex [RES][RES][RES] is returning the type std::complex (*)[256][256].

double wfc should be std::complex*** wfc.

Class member types must be known, and since you are not initialising the member variable while it is being defined, the compiler cannot deduce the type of the variable, which is why auto doesn't work as a class member type, when you aren't immediately assigning something to it. But you are assigning the value directly to the variable in your test program, allowing the compiler to deduce the type there.

Also, the new operator is returning a pointer to an array of uninitialised std::complex<double>** pointers. You need to call new for all of the uninitialised pointers.

std::complex<double>*** wfc;

wfc = new std::complex<double>** [RES];

for(int i = 0; i < RES; i++) {
    wfc[i] = new std::complex<double>* [RES];

    for(int j = 0; j < RES; j++) {
        wfc[i][j] = new std::complex<double> [RES];

        for(int k = 0; k < RES; k++) {
            wfc[i][j][k] = /* insert default value here */;
        }
    }
}

The error message returns the correct declaration, std::complex<double>(*wfc)[RES][RES];.

const unsigned int RES = 256;
struct Settings {};
struct Operators {
public:
    std::complex<double>(*wfc)[RES][RES];         // edited, see 'spitconsumers' comment

    Operators(Settings& set) {        // just another structure used by Operators
        wfc = new std::complex<double>[RES][RES][RES];

        // ...Initializing wfc using Settings
        // Setting the last element
        wfc[254][254[254] = 42;

    };
}
Related