Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Мужики, помогите! проблемы с динамическими массивами...

5.4K
16 августа 2004 года
kkip
16 / / 10.01.2004
1) Как узнать текущее кол-во элементов динамического массива??

Я, обычно веду для этого отдельную переменную, но сейчас, когда

я всё переписал и хорошенько инкапсулировал, понимаю, что если я

буду определять размер, например 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;

а вдруг память не подряд выделяется?

но при этом требуется динамическое изменение размера.

короче тут я совсем запутался. спать надо больше :)

Помогите, кто-нить!!

Динамический, "ресайзебельный" массив из объектов класса без

дефоулт-конструктора (с другим констр).

Первый вопрос тоже в силе - неудобно помнить количество

элементов динамич массива!

буду очень благодарен!
    5.9K
    16 августа 2004 года
    Iblees
    3 / / 15.01.2004
    Есть в билдере такой класс TList называется.
    Он позволяет хранить в себе указатели на любую фигню.
    Так что когда создаеш
    TList List = new TList;

    m = new abc(1);

    List->Add(m);

    m = (abc *)List->Items;

    Таким образом память не потеряеш.
    294
    16 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by Iblees
    Есть в билдере такой класс TList называется.



    IMHO, лучше std::vector использовать.

    310
    16 августа 2004 года
    fellow
    853 / / 17.03.2003
    Написать динамический массив "с нуля" самостоятельно в принципе можно. Даже полезно иногда бывает, для совершенствования мастерства в языковых механизмах. Перед этим следует разобраться с основными средствами С и С++, чётко для себя уяснить характеристики объекта в памяти и его адреса, массива объектов, массива указателей, указателя на массив, а также множество других основополагающих вещей.

    Лучшее, что можно порекомендовать - тщательное чтение добротной литературы по языку С++, Стэнли Липпмана например. Уже в ходе чтения и экспериментов большинство вопросов разъяснятся сами собой. В электронном виде литературу можно найти здесь: http://anatolix.naumen.ru/books.htm
    5.4K
    17 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by Iblees
    Есть в билдере такой класс TList называется.
    Он позволяет хранить в себе указатели на любую фигню.
    Так что когда создаеш
    TList List = new TList;

    m = new abc(1);

    List->Add(m);

    m = (abc *)List->Items;

    Таким образом память не потеряеш.



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

    а тут вообще такой вопрос уточняется:
    если я просто дорезервирую место

    new abc(1);

    то я действительно не всегда буду получать адреса, расположенные по-порядку?? (чтобы потом использовать один указатель, и шагать от него размером abc)

    5.4K
    17 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by Plisteron


    IMHO, лучше std::vector использовать.



    а мона чуть подробнее, с примерчиком??

    5.4K
    17 августа 2004 года
    kkip
    16 / / 10.01.2004
    на счет лит-ры, я уже довига перечитал, куча книг валяется по С++, больше всего нравится "Специальный справочник" Бориса Карпова. Из зарубежной (оторую я обычно больше уважаю только из за Страустрапа, все равно в россии лучше кодеры, чем у них - СПбИТМО, в которое я поступил, тому доказательство :)) из зарубежной, валяется одна ламаковая книжка, для начинающих (правда там в конце книги на CodeWarrior пишут игруху с DirrectX, "нифига себе начало", для работающих только в CBuilder, поясню, что в CW придется хорошенько знать принципы работа процесса под Windows (WinProc, WinMain) )

    короче, пока я все читал - стал фанатом СИ :)) помню, как долго вобще не мог въехать в понятие указателей :) помню, как шугался терминов "инкапсуляция, полиморфизм", а когда встретил
    int** a;
    вообще чуть крыша не потекла, а постепенно в практике, как все встречаешь, так и понимается все сразу :) СИ рулез!

    Ближе к теме:
    вобщем, как я понял, про один указатель+шаг мне можно забыть, попробую управиться с массивом указателей на объекты. Тогда вопрос так стоит:
    можно ли динамически расширить динамический массив (указателей) ??? А можно потом сужать??? и в конце концов :)) как определить размер (кол-во елементов) дин массива ?? (с помощью sizeof?)
    3
    17 августа 2004 года
    Green
    4.8K / / 20.01.2000
    Цитата:
    Originally posted by kkip
    на счет лит-ры, я уже довига перечитал, куча книг валяется по С++


    Что-то я сомневаюсь. Видимо, ты невнимательно читал, судя по вопросам и подходу к использованию С++.

    Цитата:
    Originally posted by kkip
    Из зарубежной (оторую я обычно больше уважаю только из за Страустрапа, все равно в россии лучше кодеры, чем у них - СПбИТМО, в которое я поступил, тому доказательство :)) из зарубежной,


    Почему-то уверен, что Страуструпа ты вовсе не читал. Да и утверждения твои по поводу зарубежной литературы наивны и неправильны. Ты, случаем, не по серии "... for dummers" судишь?

    Цитата:
    Originally posted by kkip
    валяется одна ламаковая книжка, для начинающих (правда там в конце книги на CodeWarrior пишут игруху с DirrectX, "нифига себе начало", для работающих только в CBuilder, поясню, что в CW придется хорошенько знать принципы работа процесса под Windows (WinProc, WinMain) )


    :D
    Особенно понравилось разъяснение "для работающих в CBulder".
    Может, эта книга для тебя самое то?

    Цитата:
    Originally posted by kkip
    короче, пока я все читал - стал фанатом СИ :))


    Так Си или C++?

    Цитата:
    Originally posted by kkip
    помню, как долго вобще не мог въехать в понятие указателей :) помню, как шугался терминов "инкапсуляция, полиморфизм", а когда встретил
    int** a;
    вообще чуть крыша не потекла, а постепенно в практике, как все встречаешь, так и понимается все сразу :) СИ рулез!


    Вообще-то, нет в Си инкапсуляции и полиморфизма...

    Цитата:
    Originally posted by kkip
    Тогда вопрос так стоит:
    можно ли динамически расширить динамический массив (указателей) ??? А можно потом сужать???


    Можно... реаллоцированием.
    Вот только лучше изучить C++ и STL, как его часть.

    Цитата:
    Originally posted by kkip

    и в конце концов :)) как определить размер (кол-во елементов) дин массива ?? (с помощью sizeof?)


    А sizeof чего ты решил брать?
    Информация к размышлению: sizeof вычисляется на этапе компиляции (compile-time), а динамический массив, ты вроде бы как создаешь в run-time...
    Кроме того, если уж ты создаешь динамический массив, то кому как не тебе знать его размер.

    310
    18 августа 2004 года
    fellow
    853 / / 17.03.2003
    Да развод ёжиков это всё! Шалун kkip :D
    294
    18 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by kkip
    а мона чуть подробнее, с примерчиком??


    Пример со скупыми комментариями (правда, не с vector, а с list, но они очень похожи, где-то одно лучше, где-то другое):

    Код:
    #include <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); //  нужные параметры
            }
        }
    }


    в заключение отмечу, что, если нужен двухмерный список, можно написать:
     
    Код:
    typedef std::list < list<MyUchDesc> > MyUchDescDoubleDimensionListType;
    3
    18 августа 2004 года
    Green
    4.8K / / 20.01.2000
    Цитата:
    Originally posted by Plisteron

    Пример со скупыми комментариями (правда, не с vector, а с list, но они очень похожи, где-то одно лучше, где-то другое):

    <Skip>
    <Skip>
    <Skip>
    <Skip>



    Ну не фига себе... крякозябр...
    Ты специально запугать человека хотел? :D

    5.4K
    19 августа 2004 года
    kkip
    16 / / 10.01.2004
    > утверждения твои по поводу зарубежной литературы...
    :) Я ничего не имею против ни того ни другого, много сделали авторы обеих, но надеюсь, не имелось ввиду, что "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, в котором прятался какойнить жук?

    Вроде на все ответил, ща еще тот рисунок поишщу :)
    5.4K
    19 августа 2004 года
    kkip
    16 / / 10.01.2004
    еще ысли появились! если я правельно все понял с реаллокацией, то как же оптимицировать использование памяти?

    в проекте, который мне подкинули, сейчас я так реализывываю:

    clacc TManager{
    ...
    void AddObject()...
    ...
    } Manager;

    class TObject{
    ...
    } **Obj;

    т.е. можно расширять только на один объект!
    в принципе, поскольку я использую "**" это совсем не заметно, при небольшом кол-ве элементов. Но если бы я использовал просто массив объектов, мне привлось б занимать памяти в 2 раза больше на время реаллокации! Какие лазейки мне представляются:

    1) Выделять заранее больше элементов, чтобы не каждый раз прешлось реаллоцировать, а иногда дописывать в заранее созданные пустые ячейки (но тогда точно придется везти размер массива в переменной).

    2) А ведь когда он выделяет новые адреса, может же получится так, что адреса за массивом сфободны, зачем же тогда так долго реаллоцировать, если можно просто чуть расширить границы :)

    Кстати прикольный форум, развод ёжиков вставил прямо картинкой, я думал будет только ссылка для скачивания аттача
    6.3K
    19 августа 2004 года
    xTrim
    38 / / 11.06.2004
    если тебе нужно написать свой динамический массив, то пожалуйста. а если хочешь просто его использовать, то не надо изобретать велосипеды. лучше почитай Страуструпа (автора С++ кстати) и используй vector.

    #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);
    294
    19 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by kkip
    еще ысли появились! если я правельно все понял с реаллокацией, то как же оптимицировать использование памяти?


    Забудь про реаллокацию. Большой риск где-нибудь так напортачить при реализации, что не сразу косяк найдёшь.
    Можно, конечно, поизобретать велосипед в виде двунаправленного списка, что-то типа:

    Код:
    class MyObj
    {
    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!
    Код:
    #include <list>
    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";
    }
    5.4K
    19 августа 2004 года
    kkip
    16 / / 10.01.2004
    вот теперь про лист и вектор всё гораздо нагляднее, пасиба :)
    пойду попробую :)
    а про "Большой риск где-нибудь так напортачить" это я уже ощютил на свей шкуре :)
    надеюсь, что с эффективностью листа и вектора создатели не напортачили!
    3
    19 августа 2004 года
    Green
    4.8K / / 20.01.2000
    Цитата:
    Originally posted by Plisteron

    Код:
    #include <list>
    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.

    Кроме того

    ВНИМАНИЕ!
    ОФИГИТЕЛЬНАЯ утечка памяти!

    5.4K
    19 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by Green


    У std::list нет метода add.

    Кроме того

    ВНИМАНИЕ!
    ОФИГИТЕЛЬНАЯ утечка памяти!



    ктонить мне разъяснит, в чем разница между list и vector??

    я достал свой не очень старый проектик, где я использовал для массивов TCheckedListBox (или как его). т.е. мне компонент сам был ненужен (он скрыт на форме), но нужен массив, с которым легко общаться+бит для каждого елемента (поэтоме checked). (разумеется, я понимаю, насколько это был ламаковый стиль, но к тому времени, я подругому не умел, использовать фиксированный максимальный размер не выгодно, да и с компонентом куда надежнее, но, конечно, значительно медленнее)

    вот ету прогу я и подогнал под VECTOR. Вроде, после пары очепяток, усё компильнулось, но пока есть внешние ошибки, раньше (с chlist) прога работала как я хотел, сейчас где-то глюк. Но я надеюсь, что ето в реализации, т.е. в алгоритме, т.к. с вектором вроде нормально работал (по методике тов xTrim)

    да, кстати, начальный элемент у него нулевой?? вроде в списках всегда нулевой (почему-то в строках - 1)

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

    и все-же, чем отличаются лист от вектора??

    294
    20 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by Green


    У std::list нет метода add.

    Кроме того

    ВНИМАНИЕ!
    ОФИГИТЕЛЬНАЯ утечка памяти!



    Ну извини, ну push_back... Второпях писал, мог и ошибиться. А насчёт утечки памяти -- сильно сомневаюсь. STL всё-таки не дураки писали.

    И потом, ты что можешь предложить?

    294
    20 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by kkip
    ктонить мне разъяснит, в чем разница между list и vector??


    В std::vector есть operator[]
    При добавлении элемента в sdt::vector, в отличие от sdt::list, длина вектора не увеличивается, и последний элемент теряется, а если не хочется терять, в stl::vector есть метод resize.
    BTW, очень хорошее описание STL имеется в MSDN.

    5.4K
    20 августа 2004 года
    kkip
    16 / / 10.01.2004
    ес, добил жуков всё работает!!

    тама много метОдов! чего они еще делают?

    и как вы думаете, можно ли самому сделать вектор быстрее?? лично я уже сомневаюсь, т.к. как я понял, он отвечает всем моим запросам по поводу оптимизации, как расширение, если след свободно, сохранение зарезервированной зоны, уплотнение и прочие...
    5.4K
    20 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by Plisteron

    В 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 !!!!

    т.е. вроде все и так работает...
    или я чего не так понял?

    294
    20 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by kkip


    эээ... странно

    я вот чего проверял, прежде чем проект переделывать:

    (отруки пишу, не ругайте сильно)

    include...
    class Tmy
    typedef...VTmy
    VTmy obj;

    obj.push_back(new Tmy(..));
    obj.push_back(new Tmy(..));
    Caption=obj.size(); //=2 !!!!

    т.е. вроде все и так работает...
    или я чего не так понял?



    Да, действительно, он сам ресайзится... Значит, ошибся я. И на старуху бывает проруха.

    5.4K
    20 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by Plisteron


    Да, действительно, он сам ресайзится... Значит, ошибся я. И на старуху бывает проруха.



    не, ну блин, ну а самое интереное - в чем же всетаки разница???

    6.3K
    20 августа 2004 года
    xTrim
    38 / / 11.06.2004
    Цитата:
    Originally posted by kkip
    не, ну блин, ну а самое интереное - в чем же всетаки разница???


    Страуструп, 3-е изд, 17.2.2

    Цитата:
    Plisteron
    А насчёт утечки памяти -- сильно сомневаюсь. STL всё-таки не дураки писали.


    проверь, чего проще. утечка действительно будет. если вместо
    MySweetList.push_back(*new MyObj());
    написать
    MySweetList.push_back(MyObj());
    будет правильней и без утечек

    5.4K
    22 августа 2004 года
    kkip
    16 / / 10.01.2004
    Цитата:
    Originally posted by xTrim

    проверь, чего проще. утечка действительно будет. если вместо
    MySweetList.push_back(*new MyObj());
    написать
    MySweetList.push_back(MyObj());
    будет правильней и без утечек



    мужики, дык помоему ето очевидно!!
    значит нас никто и не просил писать "new" - сам создал, сам удаляй - вот и утечка.

    значит усё уже сделано внутри!

    хотя я утечки не проверял...

    надо, кстати, заметить, что xTrim писал про удаление указателей!! Тогда наверно небудет утечки и при первом варианте, но зачем его вообще юзать, если можно писать "push_back(class)"

    6.3K
    23 августа 2004 года
    xTrim
    38 / / 11.06.2004
    если использовать vector<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 не удалятся
    8.4K
    24 августа 2004 года
    kolya7k
    5 / / 24.08.2004
    Цитата:
    Originally posted by kkip
    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, свои классы для такой элементарщины - чушь.

    294
    25 августа 2004 года
    Plisteron
    982 / / 29.08.2003
    Цитата:
    Originally posted by kolya7k

    Создание:
    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. Здесь

    Цитата:
    for(int i=0;i<n;i++)
    psh=(TShape*)HeapAlloc(PH,0,sizeof(TShape));


    объект создаётся? Имхо, нет, под него только память выделяется.
    4. Афаир, при уничтожении объекта list <T> он сам все свои элемента списка уничтожает и для каждого элемента вызывается деструктор, в том-то и плюс.
    5. У меня выделено памяти для 200 элементов, а потом выясняется, что надо 272. И что? Выделение новой памяти, цикл с копированием, освобождение старой? Гадость...

    Вывод: для динамических массивов HeapAlloc -- чушь.

    8.4K
    25 августа 2004 года
    kolya7k
    5 / / 24.08.2004
    Цитата:
    Originally posted by Plisteron


    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. Засеки время... Сходи чаю попей. :)

    3
    25 августа 2004 года
    Green
    4.8K / / 20.01.2000
    Цитата:
    Originally posted by kolya7k

    Да нет, все серьёзные приложения используют и менно выделение памяти, а не списки.


    Да ну?!
    Конкретные факты в студию.

    Цитата:
    Originally posted by kolya7k

    А теперь по пунктам:
    1) А изменение размера?
    Вот пожалуйста:
    psh=(TShape**)HeapReAlloc(PH,0,psh,sizeof
    (TShape*)*(n+100));


    Как здорово каждый раз заново изобретать велосипед!

    Цитата:
    Originally posted by kolya7k

    И вообще доверять все операции с СВОЕЙ памятью какому-то стороннему списку или классу - признак непрофессионализма.


    Я плакаль... :D:D:D
    А писать на C используя компилятор С++ - это признак профессионализма?
    Да, именно, ты не пишешь на С++.

    Цитата:
    Originally posted by kolya7k

    6) Приведи пример твоей разработки, которая использует списки для выделения и хранения памяти и держит при этом в себе более миллиона объектов?


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

    Цитата:
    Originally posted by kolya7k

    P.S.: Список - очень медленная штука.


    Да ты что?
    Медленная на каких операциях? Вставки/удаления?
    Медленнее, чем реаллокейт? :D

    Цитата:
    Originally posted by kolya7k

    Ты ещё скажи, что в ListView элементы добавляешь без включенного свойста OwnerData... :)


    Не понял, а какая связь между контролом, контейнером и OwnerData (кстати, было бы проще и правильнее сказать virtual list-view control)?

    P.S. Твой предыдущий пост я вообще занес в раздел "перлы". Скажи честно, ты не разбираешься в STL, шаблонах и имеешь смутное представление о ООП?

    6.3K
    25 августа 2004 года
    xTrim
    38 / / 11.06.2004
    Green полностью поддерживаю по всем пунктам. То-же самое написать хотел :D
    Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
    Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог