2017-02-06 8 views
1

Я не уверен, что это возможно. Из всех примеров, которые я видел, массив определен в скобках { }, но в моем случае это не так много.C++ Инициализация статического массива

То, что я пытаюсь сделать, это сохранить это в моей функции рисования, чтобы нарисовать несколько кругов, которые медленно увеличиваются в размере.

То, что я получаю с помощью отладчика, является то, что статический массив сбрасывается каждый раз, когда цикл попадает.

Я также пытался что-то вроде static Rect rc[5] = {}

void fun_called_every_five_seconds() { 
    static Rect rc[5]; 

    for (int i = 0; i < count; i++) { 
     int x = rand()%400; 
     int y = rand()%400; 
     int r = rand()%200; 
     rc[i] = Rect (x,y,r,r); 
    } 

    rc[0].X += 50; 


    // I check value of rc[0].X right here 
} 
+3

В каком контексте находится код? Являются ли как код, так и «статический» массив внутри функции или являются «статическими» в области пространства имен? Пожалуйста, дайте [MCVE] – KABoissonneault

+0

@KABoissonneault, добавив пример. От таймера эта функция вызывается каждые 5 секунд. –

+1

Цикл 'for' будет выполняться каждый раз, когда вы вызываете функцию. –

ответ

2

статический массив сбрасывается каждый раз, когда цикл попадает

Ну да, ваш цикл явно сбрасывает статический массив.

Минимальное изменение просто запустить цикл инициализации один раз:

void for_fun_called_every_five_seconds() { 
    static Rect rc[5]; 
    static bool init = false; 
    if (!init) { // this only happens once 
     init = true; 
     for (int i = 0; i < count; i++) { 
      int x = rand()%400; 
      int y = rand()%400; 
      int r = rand()%200; 
      rc[i] = Rect (x,y,r,r); 
     } 
    } 

    rc[0].X += 50; 

    // I check value of rc[0].X right here 
} 

, но это очень некрасиво, и излишне трудно рассуждать о. Предпочитаю что-то вроде

class Circles { 
    Rect rc[5]; 
public: 
    Circles() { 
     for (int i = 0; i < count; i++) { 
      int x = rand()%400; 
      int y = rand()%400; 
      int r = rand()%200; 
      rc[i] = Rect (x,y,r,r); 
     } 
    } 
    void for_fun_called_every_five_seconds() { 
     // should this also be in a loop, 
     // ie. each rc[i] gets increased? 
     rc[0].X += 50; 
     // I check value of rc[0].X right here 
    } 
}; 
+0

Ницца, это решение работает. Если моя программа (игра) уже не увязла с классами, я бы выбрал ее. –

+0

Возможно, также захотите использовать средства в [''] (http://en.cppreference.com/w/cpp/header/random), если вы хотите, чтобы лучшее/переносное генерирование случайных чисел – NathanOliver

+1

@EvanCarslake: вы не создавая новые классы, потому что вы использовали произвольную квоту классов для каждого проекта? Шутки в сторону? – IInspectable

1

Другой ответ в порядке, если все это не обязательно должно быть потокобезопасным.

Если инициализация должна быть потокобезопасной, нет никакой альтернативы перетаскиванию всего в декларацию.

Однако вспомогательный класс может быть использован, чтобы минимизировать ввод:

class RandomRect : public Rect { 

public: 
    RandomRect() : RandomRect(rand() % 400, rand() % 400, rand % 200) {} 
    RandomRect(int x, int y, int r) : Rect(x, y, r, r) {} 
}; 

// ... Then, initialize the static array as follows: 

static Rect rc[5]={RandomRect(), RandomRect(), RandomRect(), 
        RandomRect(), RandomRect()}; 
2

Там нет ничего, чтобы удивляться здесь. Каждый раз, когда вызывается функция, весь ее код выполняется из своих аргументов. Единственным исключением здесь будет инициализация переменной static, которая, как гарантируется, будет работать только один раз в течение всего жизненного цикла программы (также с точки зрения потоков с C++ 11). Инициализация переменной происходит только во время ее определения, на самой строке вы указываете свою переменную имя в этом контексте. Весь код после этого просто «мутирует» вашу переменную, чтобы присвоить ей значение, которое вы хотели: это не инициализация.

Здесь есть два решения. Либо вы используете std::call_once с лямбдой (см. http://en.cppreference.com/w/cpp/thread/call_once), чтобы код «инициализации» запускался только один раз. Или вы как-то вписываете весь этот код в одну строку в определение переменной. Это может быть сложно для массива C-стиля, но не для std::array, который можно легко вернуть из функций и использовать для инициализации std::array.

std::array<Rect, 5> initialize_rc() { 
    std::array<Rect, 5> rc; 

    for (int i = 0; i < count; i++) { 
     int x = rand()%400; 
     int y = rand()%400; 
     int r = rand()%200; 
     rc[i] = Rect (x,y,r,r); 
    } 

    return rc; 
} 

void for_fun_called_every_five_seconds() { 
    static std::array<Rect, 5> rc = initialize_rc(); 

    rc[0].X += 50; 

    // I check value of rc[0].X right here 
} 
2

Вы можете разделить ваш код и поместить инициализацию массива в другом месте:

auto make_rect_array() { 
    std::array<Rect, 5> rc; 

    for (int i = 0; i < count; i++) { 
     int x = rand()%400; // you may want better random 
     int y = rand()%400; 
     int r = rand()%200; 

     rc[i] = Rect (x,y,r,r); 
    } 

    return rc; 
} 

Затем просто позвонить, что в вашей функции:

void fun_called_every_five_seconds() { 
    static auto rc = make_rect_array(); 

    rc[0].X += 50; 
    // I check value of rc[0].X right here 
} 

Таким образом, вы не вводить дополнительная ветка в вашем коде, она выглядит намного чище и безопасна для потоков.

Смежные вопросы