Мужики, помогите! проблемы с динамическими массивами...
Я, обычно веду для этого отдельную переменную, но сейчас, когда
я всё переписал и хорошенько инкапсулировал, понимаю, что если я
буду определять размер, например sizeof'ом (что у меня пока не
получилось, выдается размер указателя), то я смогу значительно
увеличить надежность.
2) А началось все вот с чего.
Мне нужно было создать динамический массив элементов. Как
оказалось, использовать такой способ незя:
TShape *psh;
psh=new TShape [n];
т.к. у TShape нет defoult constructor.
я создал свой класс и начал эксперементировать:
int c=0;
class abc{
public:
int a;
abc(){c++}
abc(int r){c++}
} *m;
при создании формы сперва попробовал просто:
m=new abc;
все ок. Дальше я отключил def constr, и, разумеется, получил ту
же ошибку. Потом создовал объект другим конструктором:
m=new abc(1);
Всё ок. Т.е. пока проблем нет, всё адекватно.
Создаю массив: (def constr я, конечно вернул)
m=new abc [20];
всё ок;
А вот создать массив другим конструктором (что и требовалось для
"тшэйп") неудалось. Как я понял, нет такого формата комманды.
(или научите плиз).
Чтож, вышел из положения - гоняю циклом:
for(int i=0;i<10;i++){
m=new abc(1);
}
НУ работает... стал проверять...
for(int i=0;i<10;i++){
m=new abc(1);
m.a=1;
}
Вот когда прога (при больших "массивах") ругалось на доступ к
памяти, доменя доперло, что я написал чепуху. Сразу осознал, что
"new" возвращает и резервирует свободный адрес, который съедает
указатель.
for(int i=0;i<10;i++){
m=new abc(1);
m->a=1;
}
конечно это выход, но я не получил динамический массив
элементов, ктомуже, если я правельно понял, произойдет утечка
памяти, т.к. я, конечно, забуду ее освобождать, после потери
начального указателя.
я попробовал запоминать первый элемент и выделять остальные
"впустую":
m=new abc(1);
for(int i=0;i<10;i++){
new abc(1);
m.a=1;
} // выделяется на 1 больше, но хрен с ним, я "исследую"
вроде все работало, и не ругалось при больших числах (т.е.
небыло нарушения доступа). Но когда я представил, что у меня
несколько таких "массивов", то я понял, что это тоже чушь -
малейшее смещение при выделении памяти - и будет бооольшой и
ооочень смешной глюк!
И тут до меня доперло! Мне нужно создать динамический массив
указателей! После недолгого тырканья до меня еще доперло - для
этого мне надо использовать "указатель на указатель", и я
объявил его по-новому:
class abc{....} **m;
создание формы:
for(int i=0;i<10;i++){
m=new abc*; // пополняем массив указателей
m=new abc(1); // присваиваем новый объект
m->a=1; // пробуем с ним работать
}
вначале я немог допереть, потом въехал:
const k=10
m=new abc* [k]; // создаем массив указателей
for(int i=0;i<k;i++){
m=new abc(1); // присваиваем новый объект
m->a=1; // пробуем с ним работать
}
Вроде всё заработало, но появился главный вопрос:
КАК РАСШИРЯТЬ ДИНАМИЧЕСКИЙ МАССИВ?? (И СУЖАТЬ ЖЕЛАТЕЛЬНО)
и еще - ведь я храню почти прогрессию чисел!
может проще записать в m адрес первого, а потом:
m[i*sizeof(abc)].a=1;
а вдруг память не подряд выделяется?
но при этом требуется динамическое изменение размера.
короче тут я совсем запутался. спать надо больше :)
Помогите, кто-нить!!
Динамический, "ресайзебельный" массив из объектов класса без
дефоулт-конструктора (с другим констр).
Первый вопрос тоже в силе - неудобно помнить количество
элементов динамич массива!
буду очень благодарен!
Он позволяет хранить в себе указатели на любую фигню.
Так что когда создаеш
TList List = new TList;
m = new abc(1);
List->Add(m);
m = (abc *)List->Items;
Таким образом память не потеряеш.
Есть в билдере такой класс TList называется.
IMHO, лучше std::vector использовать.
Лучшее, что можно порекомендовать - тщательное чтение добротной литературы по языку С++, Стэнли Липпмана например. Уже в ходе чтения и экспериментов большинство вопросов разъяснятся сами собой. В электронном виде литературу можно найти здесь: http://anatolix.naumen.ru/books.htm
Есть в билдере такой класс TList называется.
Он позволяет хранить в себе указатели на любую фигню.
Так что когда создаеш
TList List = new TList;
m = new abc(1);
List->Add(m);
m = (abc *)List->Items;
Таким образом память не потеряеш.
на счет TList - это, конечно, хорошо, но хотелось бы фсе вручную :) мне как то так роднее :) а то мало ли я какой нить особенности не знаю где, а потом глюки...
а тут вообще такой вопрос уточняется:
если я просто дорезервирую место
new abc(1);
то я действительно не всегда буду получать адреса, расположенные по-порядку?? (чтобы потом использовать один указатель, и шагать от него размером abc)
IMHO, лучше std::vector использовать.
а мона чуть подробнее, с примерчиком??
короче, пока я все читал - стал фанатом СИ :)) помню, как долго вобще не мог въехать в понятие указателей :) помню, как шугался терминов "инкапсуляция, полиморфизм", а когда встретил
int** a;
вообще чуть крыша не потекла, а постепенно в практике, как все встречаешь, так и понимается все сразу :) СИ рулез!
Ближе к теме:
вобщем, как я понял, про один указатель+шаг мне можно забыть, попробую управиться с массивом указателей на объекты. Тогда вопрос так стоит:
можно ли динамически расширить динамический массив (указателей) ??? А можно потом сужать??? и в конце концов :)) как определить размер (кол-во елементов) дин массива ?? (с помощью sizeof?)
на счет лит-ры, я уже довига перечитал, куча книг валяется по С++
Что-то я сомневаюсь. Видимо, ты невнимательно читал, судя по вопросам и подходу к использованию С++.
Из зарубежной (оторую я обычно больше уважаю только из за Страустрапа, все равно в россии лучше кодеры, чем у них - СПбИТМО, в которое я поступил, тому доказательство :)) из зарубежной,
Почему-то уверен, что Страуструпа ты вовсе не читал. Да и утверждения твои по поводу зарубежной литературы наивны и неправильны. Ты, случаем, не по серии "... for dummers" судишь?
валяется одна ламаковая книжка, для начинающих (правда там в конце книги на CodeWarrior пишут игруху с DirrectX, "нифига себе начало", для работающих только в CBuilder, поясню, что в CW придется хорошенько знать принципы работа процесса под Windows (WinProc, WinMain) )
:D
Особенно понравилось разъяснение "для работающих в CBulder".
Может, эта книга для тебя самое то?
короче, пока я все читал - стал фанатом СИ :))
Так Си или C++?
помню, как долго вобще не мог въехать в понятие указателей :) помню, как шугался терминов "инкапсуляция, полиморфизм", а когда встретил
int** a;
вообще чуть крыша не потекла, а постепенно в практике, как все встречаешь, так и понимается все сразу :) СИ рулез!
Вообще-то, нет в Си инкапсуляции и полиморфизма...
Тогда вопрос так стоит:
можно ли динамически расширить динамический массив (указателей) ??? А можно потом сужать???
Можно... реаллоцированием.
Вот только лучше изучить C++ и STL, как его часть.
и в конце концов :)) как определить размер (кол-во елементов) дин массива ?? (с помощью sizeof?)
А sizeof чего ты решил брать?
Информация к размышлению: sizeof вычисляется на этапе компиляции (compile-time), а динамический массив, ты вроде бы как создаешь в run-time...
Кроме того, если уж ты создаешь динамический массив, то кому как не тебе знать его размер.
а мона чуть подробнее, с примерчиком??
Пример со скупыми комментариями (правда, не с vector, а с list, но они очень похожи, где-то одно лучше, где-то другое):
class MyUchDesc
{
private:
TRxSpinEdit *m_Uch;
TDirectoryEdit *m_Src;
TBevel *m_Spc;
TLabel *m_Upm;
TLabel *m_Dpm;
public:
__fastcall MyUchDesc(Classes::TComponent* AOwner,
int Index,
bool IsAsWin32);
int __fastcall GetUch(void) {return (int)m_Uch->Value;};
void __fastcall SetUch(int v) {m_Uch->Value = (long double)v;};
AnsiString __fastcall GetDir(void) {return m_Src->Text;};
void __fastcall SetDir(AnsiString s) { m_Src->Text = s;};
void __fastcall SetDK(TDirDialogKind newdk)
{m_Src->DialogKind = newdk;};
TDirDialogKind __fastcall GetDK(void)
{return m_Src->DialogKind;};
__fastcall ~MyUchDesc()
{
delete m_Uch;
delete m_Src;
delete m_Spc;
delete m_Upm;
delete m_Dpm;
};
};
__fastcall MyUchDesc::MyUchDesc(Classes::TComponent* AOwner, int Index, bool IsAsWin32)
{
TWinControl *wic = dynamic_cast<TWinControl*>(AOwner);
// тут создание объектов
// и установка начальных параметров,
// это скучно и неинтересно, посему опустим.
}
typedef std::list <MyUchDesc> MyUchDescListType;
MyUchDescListType UchDescVector; // только не спрашивайте меня,
// почему там List, а тут Vector (хе-хе... фраза по-черномырдински, новедь понятно?).
// Так получилось.
void __fastcall TfrmMain::spinUchCountChange(TObject *Sender)
{
int cnt = UchDescVector.size();
int vl = spinUchCount->Value;
int i;
bool IsAsWin32 = checkDirAsWin32->Checked;
if(cnt < vl)
for(i = cnt; i < vl; i++) // создаём нужное количество новых объектов
{
MyUchDesc *n = new MyUchDesc(ScrollBox1, i, IsAsWin32);
UchDescVector.push_back(*n);
}
else
for(i = cnt; i > vl; i--) // удаляем лишние
UchDescVector.pop_back();
}
void __fastcall TfrmMain::btnSetupClick(TObject *Sender)
{
if(frmSetup->ShowModal() == mrOk)
{
checkDirAsWin32->Checked = frmSetup->checkWin32Style->Checked;
TDirDialogKind dk = (checkDirAsWin32->Checked)?
dkWin32: dkVCL;
direditArchiveDir->DialogKind = dk;
edTempDir->Text = frmSetup->direditTemp->Text;
if(UchDescVector.size()) // если в списке что-то есть...
{
MyUchDescListType::iterator ii;
for(ii = UchDescVector.begin(); ii != UchDescVector.end(); ii++) // устанавливаем всем элементам
ii->SetDK(dk); // нужные параметры
}
}
}
в заключение отмечу, что, если нужен двухмерный список, можно написать:
Пример со скупыми комментариями (правда, не с vector, а с list, но они очень похожи, где-то одно лучше, где-то другое):
<Skip>
<Skip>
<Skip>
<Skip>
Ну не фига себе... крякозябр...
Ты специально запугать человека хотел? :D
:) Я ничего не имею против ни того ни другого, много сделали авторы обеих, но надеюсь, не имелось ввиду, что "rus-калл", как тогда обясняются международные победы IFMO?
> Особенно понравилось разъяснение "для работающих в CBulder".
В прошлом году я поднял науши кучу преподов, заняв первое место в области, кодя на QBasic!! Это доказывает, што куда важнее - мощь алгоритма, а не скорость или эффективность компилятора. (кста, второе место - тоже qb! мы с ним до сих пор переписываемся :))
Впервые встретился с программированием под форточки, перейдя на VisualBasic (вещь, конечно, гм, без комментариев, но куда было проще использовать известный язык, чем изучать принципиально новый). На нем я задержался около 3 мес, потихоньку въезжая в суть... дальше последовал Делфи, который я изучал прямо на одной из олимпиад (бейсиковцев домой отправляли, компилировать его никто не хотел), ну ничего, то была Всероссийская среди военных городков, за Диплом (их всего 3 было) первой степени в которой я и поступил в IFMO, с тех пор писал на Delphi. Но дело было недолго, основному я научился за пару недель. Книжки по С++ я почитывал давно, и вот окончательно решил пересесть на Builder. Сдесь ситуация обратная - IDE таже почти, язык другой. В етот раз потребовался один вечер, чтобы понять суть и переписать пару средних прог с Delphi на C++, плюс ночь, которую я разумеется не мог уснуть! К чему было это "разъяснение для работающих.." - за весь мой пёстрый курс самостоятельного обучения, хоть я и на ассемблере писал в том числе, без компиляции - в hex редакторе, но мне ниразу не доводилось встретиться с такими особенностями структуры прог под Win. В CodeWarrior (если я не ошибаюсь, и в VisualStudio тоже) нет редактора форм, и если человек, как и я раньше, никогда с такой ситуацией не встречался, то он представляет только формы и кнопочки/галочки, которые на них надо накидать и приписать код. К счастью или к горю, Builder скрывает такие навороты связанные с процессом для Win.
> Так Си или C++?
Блин, так и знал, што кто нить придерется!!
Ладно, спорить не будем, но надо же сокращать иногда :)
> Можно... реаллоцированием.
т.е. пересоздать все заново?
блин.
если я правельно понял, мне надо вот, шо сделать:
1) зарезервировать новое место на такой-же массив, только с большем кол-вом элементов.
2) скопировать туда старый массив.
3) в новый на "расширенные" поля дописать новые элементы.
4) потереть старый массив.
(для Greena, конечно, поясним, что, вчастности, пункты 3 и 4 можно поменять местами :), что сэкономит пиковое использование памяти на размер, равный размеру новых элементов)
ну усе хорошо, если использовать "=new abc[]". А если "abc(1)", то, как я понял, продолжая создовать свое управление списком, надо использовать массив указателей, и "расширять" (реаллоцировать) его.
уже лучше (если, конешно, я правельно понял реаллоцирование)
а можно ли сужать без него? delet'ом? Я, тогда должен сказать делету адрес последнего элемента, правельно? он его, походу, освободит?
т.е. размер динамического массива, ето как CDR :) можно один раз установить размер, а изменить незя, надо писать поновй (реаллоцировать)
(для Greena поясню, речь шла о РАЗМЕРЕ а не о СОДЕРЖИМОМ массива, чтобы он не сказал, что диски можно дописывать :))
т.е. все-таки мне придется хранить в переменной размер массива?
я думал, прога (или кто-там) должна помнить, шо где создавала и сколько, было бы куда удобнее узновать это у нее (да и достовернее). С одной стороны, учитывая возможность нарушения границ, кажется, что никто ничего непомнит, с другой, представляя, как это компилируется на asm, ясно, что ето сделано для ускорения, и возможность отлавливать нарушение границ, подтверждает, что где-то размер запоминается, но вот оператор delete [] это подтверждает окончательно, т.е. мне какнить можно не хранить размер в переменной?? могу ль я как нить его узнать?
> Шалун kkip
Шалить я, конечно, люблю, но вот чем я здесь успел?? :)
> "развод ёжиков"
ёжики, наверно, часто разводятся. им больно тр... :)
видели картинку из серии приколов? возвращяется ежиха и застукивает ежа с кактусом :)!
крякозябр правда большой :) особенно че-то много параметров в функциях, я надеялся, что описание list/vector ограничется его методами и свойствами :) сейчас я слишком сонный, что разбирать здоровый чужой код, но обязательно сохраню, шоб сравнить с тем, что получется у меня с "ручным" управлением :)
главное - проверить, небудет ли у меня утечки!! че-то в другой теме я читал, что у Buildera, в отличии от VC++ с етим проблемы (особенно "type** a"). Я полностью согласен, что здесь дело кривых рук, но история про перекомпиляцию на VC++ интересна. Может она объясняется выкидыванием VCL, в котором прятался какойнить жук?
Вроде на все ответил, ща еще тот рисунок поишщу :)
в проекте, который мне подкинули, сейчас я так реализывываю:
clacc TManager{
...
void AddObject()...
...
} Manager;
class TObject{
...
} **Obj;
т.е. можно расширять только на один объект!
в принципе, поскольку я использую "**" это совсем не заметно, при небольшом кол-ве элементов. Но если бы я использовал просто массив объектов, мне привлось б занимать памяти в 2 раза больше на время реаллокации! Какие лазейки мне представляются:
1) Выделять заранее больше элементов, чтобы не каждый раз прешлось реаллоцировать, а иногда дописывать в заранее созданные пустые ячейки (но тогда точно придется везти размер массива в переменной).
2) А ведь когда он выделяет новые адреса, может же получится так, что адреса за массивом сфободны, зачем же тогда так долго реаллоцировать, если можно просто чуть расширить границы :)
Кстати прикольный форум, развод ёжиков вставил прямо картинкой, я думал будет только ссылка для скачивания аттача
#include <vector>
typedef std::vector<TShape*> ShapeVect;
ShapeVect shapes;
// создаем
for(int i=0;i!=100;i++)
{
TShape* t = new TShape(Form1);
t->Parent = Form1;
t->Top = i;
t->Left = i;
shapes.push_back(t);
}
// удаляем несколько элементов
for(ShapeVect::iterator i=shapes.begin()+25;i!=shapes.begin()+75;i++)
delete (*i);
shapes.erase(shapes.begin()+25,shapes.begin()+75);
// сжимаем вектор
// тут shapes.size()=50;
// shapes.capacity()=128;
ShapeVect cl(shapes);
shapes.swap(cl);
// тут shapes.size()=50;
// shapes.capacity()=50;
// обращение к элементам
shapes[25]->Shape = stCircle;
// удаление указателей
// хотя в данном случае не критично
for(ShapeVect::iterator i=shapes.begin();i!=shapes.end();i++)
delete (*i);
еще ысли появились! если я правельно все понял с реаллокацией, то как же оптимицировать использование памяти?
Забудь про реаллокацию. Большой риск где-нибудь так напортачить при реализации, что не сразу косяк найдёшь.
Можно, конечно, поизобретать велосипед в виде двунаправленного списка, что-то типа:
{
public:
MyObj *Prev;
MyObj *Next;
double u;
MyObj() { u = 0.0; };
MyObj AppendNew()
{
MyObj *tmp = new MyObj;
tmp->Prev = this;
this->Next = tmp;
};
~MyObj() { this->Next->Prev = this->Prev->Next; };
};
Но -- не побоюсь повтора -- используй STL!
class MyObj
{
public:
double u;
};
typedef std::list<MyObj> MyObjListType;
MyObjListType MySweetList;
void main(void)
{
for(int i = 0; i < 1000; i++) // добавляем
MySweetList.add(*new MyObj()]);
for(MyObjListType::iterator ii = MySweetList.begin(); ii != MySweetList.end(); ii++) // печатаем
cout << ii->u << "\n";
}
пойду попробую :)
а про "Большой риск где-нибудь так напортачить" это я уже ощютил на свей шкуре :)
надеюсь, что с эффективностью листа и вектора создатели не напортачили!
class MyObj
{
public:
double u;
};
typedef std::list<MyObj> MyObjListType;
MyObjListType MySweetList;
void main(void)
{
for(int i = 0; i < 1000; i++) // добавляем
MySweetList.add(*new MyObj()]);
for(MyObjListType::iterator ii = MySweetList.begin(); ii != MySweetList.end(); ii++) // печатаем
cout << ii->u << "\n";
}
У std::list нет метода add.
Кроме того
ВНИМАНИЕ!
ОФИГИТЕЛЬНАЯ утечка памяти!
У std::list нет метода add.
Кроме того
ВНИМАНИЕ!
ОФИГИТЕЛЬНАЯ утечка памяти!
ктонить мне разъяснит, в чем разница между list и vector??
я достал свой не очень старый проектик, где я использовал для массивов TCheckedListBox (или как его). т.е. мне компонент сам был ненужен (он скрыт на форме), но нужен массив, с которым легко общаться+бит для каждого елемента (поэтоме checked). (разумеется, я понимаю, насколько это был ламаковый стиль, но к тому времени, я подругому не умел, использовать фиксированный максимальный размер не выгодно, да и с компонентом куда надежнее, но, конечно, значительно медленнее)
вот ету прогу я и подогнал под VECTOR. Вроде, после пары очепяток, усё компильнулось, но пока есть внешние ошибки, раньше (с chlist) прога работала как я хотел, сейчас где-то глюк. Но я надеюсь, что ето в реализации, т.е. в алгоритме, т.к. с вектором вроде нормально работал (по методике тов xTrim)
да, кстати, начальный элемент у него нулевой?? вроде в списках всегда нулевой (почему-то в строках - 1)
отлаживать стало сложнее, раньше я мог сделать элемент видимым, и смотреть список визуально на форме, а теперь хреновее.
и все-же, чем отличаются лист от вектора??
У std::list нет метода add.
Кроме того
ВНИМАНИЕ!
ОФИГИТЕЛЬНАЯ утечка памяти!
Ну извини, ну push_back... Второпях писал, мог и ошибиться. А насчёт утечки памяти -- сильно сомневаюсь. STL всё-таки не дураки писали.
И потом, ты что можешь предложить?
ктонить мне разъяснит, в чем разница между list и vector??
В std::vector есть operator[]
При добавлении элемента в sdt::vector, в отличие от sdt::list, длина вектора не увеличивается, и последний элемент теряется, а если не хочется терять, в stl::vector есть метод resize.
BTW, очень хорошее описание STL имеется в MSDN.
тама много метОдов! чего они еще делают?
и как вы думаете, можно ли самому сделать вектор быстрее?? лично я уже сомневаюсь, т.к. как я понял, он отвечает всем моим запросам по поводу оптимизации, как расширение, если след свободно, сохранение зарезервированной зоны, уплотнение и прочие...
В std::vector есть operator[]
При добавлении элемента в sdt::vector, в отличие от sdt::list, длина вектора не увеличивается, и последний элемент теряется, а если не хочется терять, в stl::vector есть метод resize.
BTW, очень хорошее описание STL имеется в MSDN.
эээ... странно
я вот чего проверял, прежде чем проект переделывать:
(отруки пишу, не ругайте сильно)
include...
class Tmy
typedef...VTmy
VTmy obj;
obj.push_back(new Tmy(..));
obj.push_back(new Tmy(..));
Caption=obj.size(); //=2 !!!!
т.е. вроде все и так работает...
или я чего не так понял?
эээ... странно
я вот чего проверял, прежде чем проект переделывать:
(отруки пишу, не ругайте сильно)
include...
class Tmy
typedef...VTmy
VTmy obj;
obj.push_back(new Tmy(..));
obj.push_back(new Tmy(..));
Caption=obj.size(); //=2 !!!!
т.е. вроде все и так работает...
или я чего не так понял?
Да, действительно, он сам ресайзится... Значит, ошибся я. И на старуху бывает проруха.
Да, действительно, он сам ресайзится... Значит, ошибся я. И на старуху бывает проруха.
не, ну блин, ну а самое интереное - в чем же всетаки разница???
не, ну блин, ну а самое интереное - в чем же всетаки разница???
Страуструп, 3-е изд, 17.2.2
А насчёт утечки памяти -- сильно сомневаюсь. STL всё-таки не дураки писали.
проверь, чего проще. утечка действительно будет. если вместо
MySweetList.push_back(*new MyObj());
написать
MySweetList.push_back(MyObj());
будет правильней и без утечек
проверь, чего проще. утечка действительно будет. если вместо
MySweetList.push_back(*new MyObj());
написать
MySweetList.push_back(MyObj());
будет правильней и без утечек
мужики, дык помоему ето очевидно!!
значит нас никто и не просил писать "new" - сам создал, сам удаляй - вот и утечка.
значит усё уже сделано внутри!
хотя я утечки не проверял...
надо, кстати, заметить, что xTrim писал про удаление указателей!! Тогда наверно небудет утечки и при первом варианте, но зачем его вообще юзать, если можно писать "push_back(class)"
for(iterator i=vect.begin();i!=vect.end();i++)
delete (*i);
vect.clear();
в vector<class> удалением объектов управляет сам вектор, ничего делать не надо.
MySweetList.push_back(*new MyObj()); будет утечка т.к. это идентично
MyObj *temp = new MyObj();
MySweetList.push_back(*temp); // в вектор записывается копия temp
// temp не удалятся
1) Как узнать текущее кол-во элементов динамического массива??
Я, обычно веду для этого отдельную переменную, но сейчас, когда
я всё переписал и хорошенько инкапсулировал, понимаю, что если я
буду определять размер, например sizeof'ом (что у меня пока не
получилось, выдается размер указателя), то я смогу значительно
увеличить надежность.
2) А началось все вот с чего.
Мне нужно было создать динамический массив элементов. Как
оказалось, использовать такой способ незя:
TShape *psh;
psh=new TShape [n];
т.к. у TShape нет defoult constructor.
Что-то вы народ совсем не туда полезли...
Массив объектов создаётся так (пример с TShape):
int n=10;
TShape **psh=new TShape *[n];
for(int i=0;i<n;i++)
psh=new TShape(Form1);
И надо не забыть ВСЁ удалить:
for(int i=0;i<n;i++)
delete psh;
delete [] psh;
Но лучше всего для всех операций с памятью использовать HeapAlloc;
Тогда мой приvер выглядел бы так:
Создание:
HANDLE PH=GetProcessHeap();
int n=10;
TShape **psh=(TShape**)HeapAlloc(PH,0,sizeof(psh)*n);
for(int i=0;i<n;i++)
psh=(TShape*)HeapAlloc(PH,0,sizeof(TShape));
Удаление:
for(int i=0;i<n;i++)
HeapFree(PH,0,psh);
HeapFree(PH,0,psh);
Определение количества элементов массива:
HeapSize(PH,0,psh)/sizeof(psh);
Всё элементарно просто.
P.S.: TList, vector, свои классы для такой элементарщины - чушь.
Создание:
HANDLE PH=GetProcessHeap();
int n=10;
TShape **psh=(TShape**)HeapAlloc(PH,0,sizeof(psh)*n);
for(int i=0;i<n;i++)
psh=(TShape*)HeapAlloc(PH,0,sizeof(TShape));
Удаление:
for(int i=0;i<n;i++)
HeapFree(PH,0,psh);
HeapFree(PH,0,psh);
Определение количества элементов массива:
HeapSize(PH,0,psh)/sizeof(psh);
Всё элементарно просто.
P.S.: TList, vector, свои классы для такой элементарщины - чушь.
1. А изменение размера?
2. Я хочу выкинуть, скажем, 147-й элемент списка. И что? Цикл? Бе... Гадость...
3. Здесь
psh=(TShape*)HeapAlloc(PH,0,sizeof(TShape));
объект создаётся? Имхо, нет, под него только память выделяется.
4. Афаир, при уничтожении объекта list <T> он сам все свои элемента списка уничтожает и для каждого элемента вызывается деструктор, в том-то и плюс.
5. У меня выделено памяти для 200 элементов, а потом выясняется, что надо 272. И что? Выделение новой памяти, цикл с копированием, освобождение старой? Гадость...
Вывод: для динамических массивов HeapAlloc -- чушь.
1. А изменение размера?
2. Я хочу выкинуть, скажем, 147-й элемент списка. И что? Цикл? Бе... Гадость...
3. Здесь
объект создаётся? Имхо, нет, под него только память выделяется.
4. Афаир, при уничтожении объекта list <T> он сам все свои элемента списка уничтожает и для каждого элемента вызывается деструктор, в том-то и плюс.
5. У меня выделено памяти для 200 элементов, а потом выясняется, что надо 272. И что? Выделение новой памяти, цикл с копированием, освобождение старой? Гадость...
Вывод: для динамических массивов HeapAlloc -- чушь.
Да нет, все серьёзные приложения используют и менно выделение памяти, а не списки.
А теперь по пунктам:
1) А изменение размера?
Вот пожалуйста:
psh=(TShape**)HeapReAlloc(PH,0,psh,sizeof
(TShape*)*(n+100));
2) Да нет. Обычно в таких массивах удаляется этот элемент и дальше два варианта:
а) Лёгкий: использовать memmove(), чтобы сдвинуть массив на один элемент.
б) Сложный: Перемещаем последний элемент массива на место удалённого. Корректность доступа по индексам обеспечивается наличием дополнительного массива индексов, определяющего в каком порядке в основном массиве следуют объекты.
Дополнительнй массив двигать и очищать не обязательно.
Таким способом у меня реализована база фирм и предприятий. Держит до 10000000 записей. Неограниченный размер данных, загрузка 10000000 меньше 1 секунды, сохранение в течении 5 секунд.
Поиск всех элементов меньше 1 секунды.
Сортировка, удаление добавление без операций с памятью (очень быстро).
Использую TListView вкупе с тем, что я описал выше.
3) Да, ты прав. Обычно я конструкторы сам вызываю для всех элементов, но если надо сразу, то
for(int i=0;i<n;i++)
psh=new TShape(this);
for(int i=0;i<n;i++)
delete psh;
4) Ага, а если объект создан нестандартным образом? То фиг. И вообще доверять все операции с СВОЕЙ памятью какому-то стороннему списку или классу - признак непрофессионализма. И знаешь сколько он будет их уничтожать?
5) См. пункт 1.
6) Приведи пример твоей разработки, которая использует списки для выделения и хранения памяти и держит при этом в себе более миллиона объектов?
P.S.: Список - очень медленная штука. На 100-1000 у тебя он работать будет почти так же быстро, но на 10000-1000000 элементах загнётся.
Ты ещё скажи, что в ListView элементы добавляешь без включенного свойста OwnerData... :)
Ели ДА(?), то попробуй добавить, скажем, 1 миллион объектов в ListView. Засеки время... Сходи чаю попей. :)
Да нет, все серьёзные приложения используют и менно выделение памяти, а не списки.
Да ну?!
Конкретные факты в студию.
А теперь по пунктам:
1) А изменение размера?
Вот пожалуйста:
psh=(TShape**)HeapReAlloc(PH,0,psh,sizeof
(TShape*)*(n+100));
Как здорово каждый раз заново изобретать велосипед!
И вообще доверять все операции с СВОЕЙ памятью какому-то стороннему списку или классу - признак непрофессионализма.
Я плакаль... :D:D:D
А писать на C используя компилятор С++ - это признак профессионализма?
Да, именно, ты не пишешь на С++.
6) Приведи пример твоей разработки, которая использует списки для выделения и хранения памяти и держит при этом в себе более миллиона объектов?
Уважаемый, мы даже при написании драйверов используем классы контейнеров. Модифицированные, конечно, но модификация в основном касается потокобезопасности.
P.S.: Список - очень медленная штука.
Да ты что?
Медленная на каких операциях? Вставки/удаления?
Медленнее, чем реаллокейт? :D
Ты ещё скажи, что в ListView элементы добавляешь без включенного свойста OwnerData... :)
Не понял, а какая связь между контролом, контейнером и OwnerData (кстати, было бы проще и правильнее сказать virtual list-view control)?
P.S. Твой предыдущий пост я вообще занес в раздел "перлы". Скажи честно, ты не разбираешься в STL, шаблонах и имеешь смутное представление о ООП?