Инициализация динамического массива

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Добрый день, камрады. Подскажите, есть ли какой то способ инициализировать динамически

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ты бы хоть код привёл. Что за массив?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Черт, рука дрогнула. Начну сначала:

Добрый день, камрады. Подскажите, есть ли какой то способ инициализировать динамический массив при создании:

Есть такой класс: 

01class TsButton {
02 
03public:
04  TsButton()
05    : _posX(0), _posY(0), _style(SIZE_3_FULL), _namesIndex(0){};
06 
07  TsButton(const uint16_t posX, const uint16_t posY, const Style style, uint8_t index)
08    : _posX(posX), _posY(posY), _style(style), _namesIndex(index){};
09 
10  friend bool operator==(const TsButton &button, const TS_Point &point);
11 
12  int16_t _posX;
13  int16_t _posY;
14  Style _style;
15  uint8_t _namesIndex;
16};

Нужен массив классов, создаю и инициализирую так:

01uint8_t menuButtonsNumber = 3;
02const uint8_t verticalGap = (DISPLAY_HEIGHT - (menuButtonsNumber + 1) * 10) / menuButtonsNumber;
03TsButton* tsButton_ptr = new TsButton[menuButtonsNumber];
04 
05    for (uint8_t buttonNumber = 0; buttonNumber < menuButtonsNumber; buttonNumber++) {
06      tsButton_ptr[buttonNumber]._posX = 10;
07      tsButton_ptr[buttonNumber]._posY = 10 + (10 + verticalGap) * buttonNumber;
08      tsButton_ptr[buttonNumber]._style = pgm_read_byte(&menu[menuFirstLine + buttonNumber].style);
09      tsButton_ptr[buttonNumber]._namesIndex = menuFirstLine + buttonNumber;
10    }

Очень хотелось бы сделать члены массива константными, но не соображу способ инициализации массива при создании. Буду признателен если подкинете идею как это сделать.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Не, нифига я вопрос не понял.

 

rkit
Offline
Зарегистрирован: 23.11.2016

Сделать члены массива классами с нетривиальным конструктором.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

вроде в строках 7-8 он и определен. не соображу как его вызвать (аргументы генерируются в цикле).

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

PS. А вообще класс с публичными полями это IMHO нонсенс.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Это продвинутая структура ))))

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

andriano пишет:

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

PS. А вообще класс с публичными полями это IMHO нонсенс.

Городить геттеры/сеттеры смысла не вижу, слишком все тривиально, но хотелось бы закрыть члены от изменения. Параметрический конструктор есть (строки 7-8), по одному инициализировать классы при создании получается, затем объявить и инициализировать ими массив тоже получается.

А как массив создать и инициализировать анонимными объектами класса - не могу сообразить.

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Тогда я тоже не понял, что Вам надо.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Один экземпляр я могу объявить и инициализировать так: 

1TsButton* tsButton2_ptr = new TsButton{ 10, 20, SIZE_3_FULL, 4 };

А хотелось бы аналогичным образом объявить и инициализировать массив:

1TsButton* tsButton2_ptr = new TsButton[2]{ 10, 20, SIZE_3_FULL, 4, 10, 20, SIZE_3_FULL, 4 };

Но никак. Хотя опой чувствую что как то можно.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Напиши отдельный метод, что мешает то?)))

1TsButton[2].Init (10, 20, SIZE_3_FULL, 4 );

 

rkit
Offline
Зарегистрирован: 23.11.2016

Dinosaur пишет:

вроде в строках 7-8 он и определен. не соображу как его вызвать (аргументы генерируются в цикле).

Там определен конструктор класса, а в массиве у тебя указатели.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А вот так можно, интересно?

01class TsButton {
02 
03public:
04  TsButton()
05    : _posX(0), _posY(0), _style(SIZE_3_FULL), _namesIndex(0){};
06 
07  TsButton(const uint16_t posX, const uint16_t posY, const Style style, uint8_t index)
08    : _posX(posX), _posY(posY), _style(style), _namesIndex(index){};
09 
10  friend bool operator==(const TsButton &button, const TS_Point &point);
11 
12  const int16_t _posX = 10;
13  const int16_t _posY = 20;
14  const Style _style = SIZE_3_FULL;
15  const uint8_t _namesIndex = 4;
16};

 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

BOOM пишет:

Напиши отдельный метод, что мешает то?)))

1TsButton[2].Init (10, 20, SIZE_3_FULL, 4 );

Так константными хочу сделать члены. Какой тут init :(

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

BOOM пишет:

А вот так можно, интересно?

1<span style="font-family:Verdana, Geneva, Arial, sans-serif;font-size:12px;"></span>

Можно, но зачем? Задача прийти к:

01class TsButton {
02 
03public:
04  TsButton(const uint16_t posX, const uint16_t posY, const Style style, uint8_t index)
05    : _posX(posX), _posY(posY), _style(style), _namesIndex(index){};
06 
07   const int16_t _posX;
08   const int16_t _posY;
09   const Style _style;
10   const uint8_t _namesIndex;
11};

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

#13 глянь. И конструктор вообще не нужен тогда, пустым остаётся.

И вообще это все на обычную структуру похоже получается. ))

1struct  TsButton {
2 
3  const int16_t _posX = 10;
4  const int16_t _posY = 20;
5  const Style _style = SIZE_3_FULL;
6  const uint8_t _namesIndex = 4;
7};

А тогда я не понимаю зачем массив структур одних и тех же значений...

b707
Offline
Зарегистрирован: 26.05.2017

Dinosaur пишет:

А хотелось бы аналогичным образом объявить и инициализировать массив:

1TsButton* tsButton2_ptr = new TsButton[2]{ 10, 20, SIZE_3_FULL, 4, 10, 20, SIZE_3_FULL, 4 };

а так?

1TsButton* tsButton2_ptr = new TsButton[2]  {
2     { 10, 20, SIZE_3_FULL, 4},
3     { 10, 20, SIZE_3_FULL, 4 }};

 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

b707 пишет:

а так?

1TsButton* tsButton2_ptr = new TsButton[2]  {
2     { 10, 20, SIZE_3_FULL, 4},
3     { 10, 20, SIZE_3_FULL, 4 }};

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

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

BOOM пишет:

А тогда я не понимаю зачем массив структур одних и тех же значений...

Так они разные (просто поленился писать другие значения и скопировал два раза одни и те же данные)

b707
Offline
Зарегистрирован: 26.05.2017

Dinosaur пишет:

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

тогда вы пошли неверным путем.

Вам надо сначала создать массив ссылок на обьекты, а потом инициализировать каждый по отдельности в цикле.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

b707 пишет:

Вам надо сначала создать массив ссылок на обьекты, а потом инициализировать каждый по отдельности в цикле.

Тут опять торможу. А разве массивы ссылок бывают? Ссылку понимаю как объявить:

1int a;
2int &ref = a;

А как массив?

b707
Offline
Зарегистрирован: 26.05.2017

Dinosaur пишет:

Тут опять торможу. А разве массивы ссылок бывают?

конечно

Только тут я неверно выразился, вам нужен не массив ссылок, а массив указателей.

И. кстати, тип переменной tsButton2_ptr в моем примере из сообщения #17 будет не TsButton* , а TsButton**

b707
Offline
Зарегистрирован: 26.05.2017

как-то так

01TsButton* button_array[ARRAY_SIZE];
02 
03for (int i =0; i<ARRAY_SIZE; i++) {
04  //генерируем парметры инициализации
05  int16_t  X = 10;
06  int16_t  Y = 20;
07  Style  style = SIZE_3_FULL;
08  uint8_t  index = 4;
09 
10 
11  button_array[i] = new TsButton{ X, Y, style, index };
12}

 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Спасибо, именно это и пытался сообразить. Меня смутил "массив ссылок", и пропустил "массив указателей на указатели". В таком виде работает как мне нужно:

1TsButton** tsButton_ptr = new TsButton*[menuButtonsNumber];
2for (uint8_t buttonNumber = 0; buttonNumber < menuButtonsNumber; buttonNumber++) {
3  int16_t posX = 10;
4  int16_t posY = 10 + (10 + verticalGap) * buttonNumber;
5  Style style = pgm_read_byte(&menu[menuFirstLine + buttonNumber].style);
6  uint8_t namesIndex = menuFirstLine + buttonNumber;
7  tsButton_ptr[buttonNumber] = new TsButton{ posX, posY, style, namesIndex };
8}

 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

В догонку вопрос по очистке памяти - так нормально будет?

1for (uint8_t buttonNumber = 0; buttonNumber < menuButtonsNumber; buttonNumber++) {
2  delete[] tsButton_ptr[buttonNumber];
3}
4delete[] tsButton_ptr;
5tsButton_ptr = nullptr;

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Зависит от того, насколько "умный" менеджер памяти.

Я предпочитаю удалять в порядке обратном выделению.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

andriano пишет:
Я предпочитаю удалять в порядке обратном выделению.

Да, спасибо за замечание, переделал.

void deleteButtonsArray() {

1for (int index = (menuButtonsNumber - 1); index >= 0; index--) {
2    delete[] tsButton_ptr[index];
3  }
4  delete[] tsButton_ptr;
5  tsButton_ptr = nullptr;
6}

andriano пишет:
Зависит от того, насколько "умный" менеджер памяти.

Тут "программист" дурак на всю голову, а вы про умный менедрер памяти. :)

Можете поподробнее раскрыть этот момент (ссылку где почитать либо кусок кода)? В поиске натыкаюсь в основном на: (почти)никода нельзя использовать new и delete, используйте vector, контейнеры и ты ды.

Вопрос кстати про delete и delete[] (код в этом сообщении) - мне кажется что в цикле нужно использовать delete (ведь удаляем не массивы, а элементы массива), а за циклом delete[] для удаления массива. Но в учебнике  в примере (ravesli) используется delete[] как в цикле, так и вне цикла, что меня ставит в тупик. Компилятор принимает оба варианта. Подскажите как правильно освободить память в данном случае.

Ну и  в догонку вопрос - а можно обойтись для рашения этой задачи без использования динамической памяти? В голову приходит сходу объявление глобального массива tsButton максимально возможного размера в стеке, и наполнение его требуемыми по ходу выполнения программы данными, но не хочется (жаба давит) чтобы постоянно была занятой память (tsButton * 10). Хотя опять же для микроконтроллеров читал что следуют всячески избегать использования динамической памяти. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я, конечно же, не настоящий самурай ))) Но что-то мне подсказывает, что вместо подобного массива удобнее использовать одно/двух-связанный список (если речь про динамически изменяемый размер). Но может быть опять не понял что ТС хочет.

b707
Offline
Зарегистрирован: 26.05.2017

Dinosaur пишет:

Ну и  в догонку вопрос - а можно обойтись для рашения этой задачи без использования динамической памяти?

А вы поподробнее опишите "эту задачу". Я так понял, динамический массив - для элементов меню? Вы его многократно создаете и уничтожаете  в ходе работы программы?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

b707 пишет:

А вы поподробнее опишите "эту задачу". Я так понял, динамический массив - для элементов меню? Вы его многократно создаете и уничтожаете  в ходе работы программы?

Да, именно так, многоуровневое меню, на некоторых уровнях количество пунктов больше, чем влазит за раз на экран, идея в том чтобы динамически формировать "кадр" из объектов которые размещены на экране и соответственно удалять обекты когда они выходят за рамки экрана и более не нужны.

Делаю обектами, чтобы после получения координат точки нажатой на тачскрике, пробегать по массиву обектов и через перегруженный оператор== проверять равенство полученной точки нажатия и кнопки, соответственно обрабатывать нажатие. Ну и опять же изучаю главу ООП, срочно хочется куда-то применить полученные знания :)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ну это и есть список, так то...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

попробуй так

https://arduino.ru/forum/otvlechennye-temy/kudryavaya-initsializatsiya-s...

шаблоном будет указатель на класс, в скобках - конструкторы new()

Gromozeka
Offline
Зарегистрирован: 06.10.2022

Создай массив указателей без new. 

В цикле для каждого элемента отдельно вызывай new c входными параметрами конструктора поиндексно. Передавай нужные параметры при каждом индексе. 

kakaxi
Offline
Зарегистрирован: 20.07.2021

Если нужно только инициализировать, то встроение в цикл не работает?