Динамический массив (массив с динамически выделяемой памятью)

kolyn
Offline
Зарегистрирован: 18.01.2019

DetSimen пишет:

 надо делать список, 

Сцуко, опять новое слово:)

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

DetSimen пишет:

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

добавлю еще - у списка есть важное преимущество - его очень легко сделать сортированным... например. для того чтобы вставить новый элемент по порядку возрастания - в массиве придется передвинуть все последующие элементы. а в списке достаточно переобределить связи всего двух ячеек

Но зато список занимает в памяти больше места, чем массив... ведь указатели на предыдущую ячейку надо где-то хранить

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

Список тем хорош, что сначала создается пустой, а потом, по мере надобности, растёт или уменьшается по желанию. т.е в разные моменты времени список имеет разное число элементов. 

А вот массив - по определению должен быть строго того размера, которым его создали. Все остальные переопределения размера - от лукаваго Бейсика. 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

В 328ом контроллере 2К памяти. Не нужно там делать списки и динамические массивы. Меняйте концепцию работы с памятью. Без конкретики ничего не посоветую. Или ESP8266 ;)). Рекурсия на 2К памяти - не наш метод! ;))

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

wdrakula пишет:

 Рекурсия на 2К памяти - не наш метод! ;))

работает же... и быстро

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

Нинаю. String же втулили, работает, и порой даже неплохо.  Чем не динамический массив?

kolyn
Offline
Зарегистрирован: 18.01.2019

DetSimen пишет:

kolyn пишет:

ППС 32 строка - создаете новый, переписываете, старый удаляете?

Естественно

Тут я неправильно задал вопрос.

Чисто технически как правильно - создать временный, копировать в него, удалить "старый", создать "новый" с ТЕМ ЖЕ ИМЕНЕМ, копировать из временного , удалить временный - так куча дырок в памяти.

Или есть какая хитрость с именами, ведь дальше надо к "новому" обращаться по тому же имени, что и к "старому"?

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

kolyn пишет:

Или есть какая хитрость с именами, ведь дальше надо к "новому" обращаться по тому же имени, что и к "старому"?

имя динамического массива - это отдельная переменная типа указатель, он вообще во всех этих "плясках" с удалением и копированием данных не участвует

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

DetSimen пишет:

Нинаю. String же втулили, работает, и порой даже неплохо.  Чем не динамический массив?

Пока их суммарно на сотню букавак. ;)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017
Поле: 
 
T* FItems;
 
Конструктор: 
 
	// конструктор. принимает начальное число элементов массива
	//
	TArray(const uint8_t ASize) {
		FItems = new T[FSize = ASize];     // первый раз запрашиваем память
		if (FItems == NULL) goto err_exit;
		Clear();
		return;
	err_exit:
//		SendMessage(msg_OutOfMemory, 0, GetClassID());
		;
	}

 

 
Ресайзер
 
	void SetNewSize(const uint8_t ANewSize) {
		if (ANewSize <= FSize) return;   // если размер такой же, или меньше то каковахрена?     

		if (FItems != NULL) {
			T* tmpAprray = new T[ANewSize]; // временный массив
			
			if (tmpAprray != NULL) { // если успешно распределили память, то 
			
				for (uint8_t i = 0; i < ANewSize; ++i) { // перенесём данные из старого в новый
					if (i < FSize)  
						tmpAprray[i] = FItems[i];
					else
						tmpAprray[i] = T();
				}

				FSize = ANewSize;
				delete[] FItems;  // старый удалим
				FItems = tmpAprray; // присвоим указателю адрес нового массива
			}
		}
	}

 

 
kolyn
Offline
Зарегистрирован: 18.01.2019
FItems = tmpAprray; // присвоим указателю адрес нового массива
А так разве можно было? Сложнаа

 

kolyn
Offline
Зарегистрирован: 18.01.2019

Оффтоп. У меня есть знакомый с фамилией Хренов. Большой любитель воздушных шаров. У него визитка, на ней два слова.

                                                                      Воздухоплаватель. Хренов.

То же о себе программист хренов))

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

kolyn пишет:

То же о себе программист хренов))

Не расстраивайся, я тоже

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

DetSimen пишет:

Если при очередном пополнении вышел за макс. число элементов, то добавлять естес-сно не 1, а сразу 8-16.  Код усложняется не намного

Моя практика говорит, что лучше не "на", а "в". Т.е. увеличивать массив не насколько-то элементов, а во сколько-то раз. Обычно полтора-два.

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

andriano пишет:

Моя практика говорит, что лучше не "на", а "в". Т.е. увеличивать массив не насколько-то элементов, а во сколько-то раз. Обычно полтора-два.

На ББ я бы так и сделал. Там я ёмкость сразу удваиваю. 

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

DetSimen пишет:

Ресайзер

realloc есть

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

rkit пишет:

realloc есть

я знаю.  :)  

тока, как я и подозревал  использование realloc для указателя, возвращаемого new[] , является неопределенным поведением.

kolyn
Offline
Зарегистрирован: 18.01.2019

ЕвгенийП пишет:

kolyn пишет:
А я на шару хотел выклянчить, готовое:))))
Нипапёрла :-(((

Клянчить уметь надо

DetSimen пишет:

Конструктор: 
	// конструктор. принимает начальное число элементов массива
Ресайзер
 
	void SetNewSize(const uint8_t ANewSize) {

rkit пишет:

realloc есть

Остался последний рывок - "памагите в кучу собрать"))

ПС Это шутка, если что...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017
// Author: DtS  16.07.2018 
// 
#pragma once
#include <Arduino.h>

template <typename T>
class TArray {
protected:
	TArray() = delete;
	TArray(TArray&) = delete;
	TArray(TArray&&) = delete;

	uint8_t FSize;
	T*		FItems;
	T		FWrongValue;

//	uint16_t GetClassID(void) const { return reinterpret_cast<uint16_t>(this); }
public:
	// конструктор. принимает начальное число элементов массива
	//
	TArray(const uint8_t ASize) {
		FItems = new T[FSize = ASize];     // первый раз запрашиваем память
		if (FItems == NULL) goto err_exit;
		Clear();
                FWrongValue = T();
		return;
	err_exit:
//		SendMessage(msg_OutOfMemory, 0, GetClassID());
		;
	}

	// если массив хранит указатели, то осторожно, память, которую хапнули указатели
	// отоматисски не освобождается, пожалуйста, do it врукопашную, если надо, 
	// чтоб избежать висячих ссылок

	void Clear(void){  
		if (FItems != NULL) {
			for (uint8_t i = 0; i < FSize; ++i) FItems[i] = T();
		}
	}

	// деструктор. Возвращает память, которую мы отхапали
	//
	~TArray() {
		delete[] FItems;
	}

	void SetNewSize(const uint8_t ANewSize) {
		if (ANewSize <= FSize) return;   // если размер такой же, то каковахрена?     

		if (FItems != NULL) {
			T* tmpAprray = new T[ANewSize]; // временный массив
			
			if (tmpAprray != NULL) { // если успешно распределили память, то 
			
				for (uint8_t i = 0; i < ANewSize; ++i) { // перенесём данные из старого в новый
					if (i < FSize)  
						tmpAprray[i] = FItems[i];
					else
						tmpAprray[i] = T();
				}

				FSize = ANewSize;
				delete[] FItems;  // старый удалим
				FItems = tmpAprray; // присвоим указателю адрес нового массива
			}
		}
	}

	// отдаёт ссылку на элемент массива

	T& operator[](const uint8_t AIndex) {
		if (FItems != NULL && AIndex < FSize)
			return FItems[AIndex];
		else {
//			SendMessage(msg_WrongIndex, AIndex, GetClassID());
			return FWrongValue;
		}
	}

	// добавить элемент в конец массива

	T operator +=(const T AValue) {
		SetNewSize(FSize + 1);
		FItems[FSize - 1] = AValue;
		return AValue;
	}

	// отдает размер массива
	//

	uint8_t GetSize(void) const { return FSize; }

	// отдаёт размер массива в байтах

	size_t GetByteSize(void) const {return FSize * sizeof(T);}
};

 

kolyn
Offline
Зарегистрирован: 18.01.2019

DetSimen пишет:

// Author: DtS  16.07.2018 

Спасибо большое, но пока смотреть не стану, постараюсь сам... Потом сравню, ляпы свои найду.

Еще раз спасибо!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

kolyn пишет:
А я на шару хотел выклянчить, готовое:))))
Нипапёрла :-(((

на шару тут тока радиолюбителям помогают, бо программисты из них никакие )))

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

ua6em пишет:

на шару тут тока радиолюбителям помогают, бо программисты из них никакие )))

почему, я очень люблю порассуждать о схемах всяких... и совершенно бесплатно, ибо не секу в этом почти ничего :)))

kolyn
Offline
Зарегистрирован: 18.01.2019

ua6em пишет:

на шару тут тока радиолюбителям помогают, бо программисты из них никакие )))

Что предлагаете? Зарегестрироваться под ником zl4yl, поставить женскую аватарку и заходить через VPN? Думаю тут такие  ̶ ̶х̶и̶т̶р̶о̶ж̶о̶  умные уже были

 

AndreyD
AndreyD аватар
Offline
Зарегистрирован: 07.10.2018

kolyn пишет:

Что предлагаете? Зарегестрироваться под ником zl4yl, поставить женскую аватарку и заходить через VPN? Думаю тут такие  ̶ ̶х̶и̶т̶р̶о̶ж̶о̶  умные уже были

Вот зачем схему аферы раскрыли, теперь как попрут. )))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

kolyn пишет:

ua6em пишет:

на шару тут тока радиолюбителям помогают, бо программисты из них никакие )))

 поставить женскую аватарку

Да!!! С сиськами!!!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

wdrakula пишет:

kolyn пишет:

ua6em пишет:

на шару тут тока радиолюбителям помогают, бо программисты из них никакие )))

 поставить женскую аватарку

Да!!! С сиськами!!!

и попросить раскрыть тему? )))