Search code examples
c++arraysmultidimensional-arrayreturn

return 2D array in C++


I am kind of new to C++ and I was doing a physics simulation in python which was taking forever to finish so I decided to switch to C++, and I don t understand how to make a function which will return a 2D array (or 3D array)

#include <iostream>
#include <cmath>
// #include <complex> //

using namespace std;

double** psiinit(int L, int n, double alpha){
    double yj[400][400] = {};
    for (int j = 0; j < n; j++)
    {
        double xi[400] = {};
        for (int i = 0; i < n; i++)
        {
            xi[i] = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
        };
        yj[j] = xi;
    };
    return yj;
}

int main(){
    int L = 10;
    int n = 400;
    int nt = 200*n;
    double alpha = 1;
    double m = 1;
    double hbar = 1;

    double x[n] = {};
    double y[n] = {};
    double t[nt] = {};

    double psi[nt][n][n] = {};
    psi[0] = psiinit(L, n, alpha);

    cout << psi <<endl;
    return 0;
}

I have look for answers but it doesn't seems to be for my kind of problems

Thanks


Solution

  • If you're new to c++ you should read about the concepts of heap and stack, and about stack frames. There are a ton of good resources for that.

    In short, when you declare a C-style array (such as yj), it is created in the stack frame of the function, and therefore there are no guarantees about it once you exit the frame, and your program invokes undefined behavior when it references that returned array.

    There are 3 options:

    1. Pass the array to the function as an output parameter (very C-style and not recommended).
    2. Wrap the array in a class (like std::array already does for you), in which case it remains on the stack and is copied to the calling frame when returned, but then its size has to be known at compile time.
    3. Allocate the array on the heap and return it, which seems to me to best suit your case. std::vector does that for you:
    std::vector<std::vector<double>> psiinit(int L, int n, double alpha){
        std::vector<std::vector<double>> yj;
        for (int j = 0; j < n; j++)
        {
            std::vector<double> xi;
            for (int i = 0; i < n; i++)
            {
                const int value = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
                xi.push_back(value);
            }
    
            yj.push_back(xi);
        }
        return yj;
    }
    

    If you're concerned with performance and all of your inner vectors are of a fixed size N, it might be better to use std::vector<std::array<double, N>>.