3

I am trying to init a static array in a function.

int query(int x, int y) {
    static int res[100][100]; // need to be initialized to -1
    if (res[x][y] == -1) {
        res[x][y] = time_consuming_work(x, y);
    }
    return res[x][y];
}

How can I achieve this?

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303
hyperbola
  • 112
  • 1
  • 7
  • You may want to learn about `for` loops. – donjuedo Jul 27 '19 at 13:52
  • @donjuedo that is not going to initialize a static array. – bolov Jul 27 '19 at 13:55
  • 2
    @Hyperbola You could just use a static boolean variable, to guard the initialization performed by a double for loop... :) EDIT: Oh, please check bolov's [answer](https://stackoverflow.com/a/57232831/2411320), which uses a λ to initialize the array..! – gsamaras Jul 27 '19 at 14:06
  • 1
    @gsamaras Thanks, a lambda is so amazing! I have never thought about using lambda like this. – hyperbola Jul 27 '19 at 14:11
  • 1
    A lambda can also be useful to initialize a `const` variable: https://stackoverflow.com/questions/46345151/conditional-invocation-of-constructor/46345224#46345224 – Robert Andrzejuk Jul 28 '19 at 09:07
  • 1
    @bolov, you are correct. I intended to only give a hint. It seems like homework after all. But if that were "hint 1", then "hint 2" would have been gsamaras comment, to use a static boolean as a guard. That's where I was going, eventually. – donjuedo Jul 28 '19 at 21:28
  • Well this is not my homework but actually what I encountered. – hyperbola Feb 19 '21 at 09:48

4 Answers4

7

First of all, I strongly recommend moving from C arrays to std::array. If you do this you can have a function to perform the initialization (otherwise you can't, as a function cannot return C arrays):

constexpr std::array<std::array<int, 100>, 100> init_query_array()
{
    std::array<std::array<int, 100>, 100> r{};
    for (auto& line : r)
        for (auto& e : line)
            e = -1;
    return r;
}

int query(int x, int y) {
    static std::array<std::array<int, 100>, 100> res = init_query_array();

    if (res[x][y] == -1) {
        res[x][y] = time_consuming_work(x, y);
    }
    return res[x][y];
}

Another option, that I actually like more is to perform the init in a lambda:

int query(int x, int y) {
    static auto res = [] {
        std::array<std::array<int, 100>, 100> r;
        for (auto& line : r)
            for (auto& e : line)
                e = -1;
        return r;
    }();

    if (res[x][y] == -1) {
        res[x][y] = time_consuming_work(x, y);
    }
    return res[x][y];
}
bolov
  • 65,999
  • 14
  • 127
  • 202
2

You can't do this. You need an explicit for loop and a flag to avoid initializing more than once:

int query(int x, int y) {
    static bool initilized = false;
    static int res[100][100]; // need to be initialized to -1
    if (!initilized) {
        initilized = true;
        for (int i = 0; i != 100; ++i) {
            for (int j = 0; j != 100; ++j) {
                res[i][j] = -1;
            }
        }
    }
    if (res[x][y] == -1) {
        res[x][y] = time_consuming_work(x, y);
    }
    return res[x][y];
}
Ayxan Haqverdili
  • 23,309
  • 5
  • 37
  • 74
1

You can do it for example the following way by means of introducing one more static variable

int query(int x, int y) {
    static bool initialized;
    static int res[100][100]; // need to be initialized to -1

    if ( not initialized )
    {
        for ( auto &row : res )
        {
            for ( auto &item : row ) item = -1;
        }

        initialized = true;
    }        

    if (res[x][y] == -1) {
        res[x][y] = time_consuming_work(x, y);
    }
    return res[x][y];
}
Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303
1

You can use fill with std::array and a IIL(immediately invoked lambda) :

static std::array<std::array<int, 100>, 100> res = [] () {
     std::array<int, 100> default_arr;
     default_arr.fill(-1);

     std::array<std::array<int, 100>, 100> ret;
     ret.fill(default_arr);

     return ret;
}();
Robert Andrzejuk
  • 4,923
  • 2
  • 22
  • 30