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
  • 301,070
  • 26
  • 186
  • 335
hyperbola
  • 127
  • 2
  • 10
  • 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
  • 72,283
  • 15
  • 145
  • 224
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];
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
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
  • 301,070
  • 26
  • 186
  • 335
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
  • 5,076
  • 2
  • 22
  • 31