Конференция "Начинающим" » Динамические массивы и SetLength [D7]
 
  • Вячеслав (26.02.17 21:42) [0]
    Здравствуйте.
    Код ниже прекрасно работает с SetLength(array,1). Зачем выделять какую-то конкретную память больше 1? У меня только одна догадка, возможно реализация динамических массивов работает в разы быстрее, если память выделить зарание. Но если скорость не так важна, удобнее использовать минимальный размер массива, коотрый автоматом расширяется до некого неизвестного размера.
    var
     a: array of integer;
    begin
     { TODO -oUser -cConsole Main : Insert code here }

     SetLength(a,1);
     a[0] := 0;
     a[1] := 1;
     a[2] := 2;
     a[3] := 3;
     a[4] := 4;

     WriteLn(a[0]);
     WriteLn(a[1]);
     WriteLn(a[2]);
     WriteLn(a[3]);
     WriteLn(a[4]);

    end.

  • Sha © (26.02.17 23:39) [1]
    Попробуй a[1000000]:=1000000;

    Потом поразмысли относительно памяти,
    в частности, как бы ты сам ее выделял и контролировал использование,
    если бы работал менеджером памяти.
  • Вячеслав (26.02.17 23:54) [2]
    Ну а в чём разница

    SetLength(a,1);
    a[1000000]:=1000000;



    и

    SetLength(a,1000000);
    a[1000000]:=1000000;



    ?
  • Вячеслав (26.02.17 23:56) [3]
    + UPD, я понимаю, если надо убрать лишние элементы с конца динамического массива. Тогда имеет смысл сократить память на неиспрользуемую дельту. Опять же, если она именно с конца. Но я не понимаю механизма в динамическом массиве зарание выделять кол-во используемых элементов!?!
  • Inovet © (27.02.17 00:19) [4]
    Чтобы расширить размер, надо выделить дополнительную память в конце массива, если она не зарезервирована заранее. Может оказаться, и чаще всего так будет, что память за массивом уже занята, тогда надо выделить в другом месте полный объём и скопировать в него все элементы массива, старый участок освободить. Представь себе, что будет, если это проделывать для каждого нового элемента. Во-первых, скорость, во-вторых фрагментация.
  • dmk © (27.02.17 00:35) [5]
    >динамическом массиве
    Вот именно. Его можно расширить, сжать и обнулить.
    Не динамический массив придется обнулить и создать заново.
  • Kilkennycat © (27.02.17 02:09) [6]
    списки круче.

    > Вячеслав   (26.02.17 23:54) [2]
    > Ну а в чём разница
    >
    > SetLength(a,1);
    > a[1000000]:=1000000;
    > и
    > SetLength(a,1000000);
    > a[1000000]:=1000000;
    >
    > ?

    в данном примере первая часть эвивалентна второй в такой записи:
    SetLength(a,1);
    SetLength(a,1000000);
    a[1000000]:=1000000;
    если не учитывать ошибку;
    но если ошибку учитывать, то они равнозначны
  • Вячеслав (27.02.17 12:27) [7]
    Понял.
    Подскажите, есть ли в языке готовая такая "сущность", которая имитирует некий резиновый динамический массив или хеш, который расширяется автоматом при добавлении в него элемента?
    По сути для меня есть только 2 требования (синтаксис не важен):
    1) a[] = 1 или a[Size(a)-1] = 1 автоматом добавляет элемент в конец массива и увеличивает его Size\Length на еденицу.
    2) Есть метод или функция удаления элемента, что мнговенно влияет на Size или Length. Т.е. я всегда могу знать, сколько значимых элементов в этом динамическом массиве измеряв его.
  • Kilkennycat © (27.02.17 12:30) [8]
    TList идеально подходит, если требования только эти.
  • Германн © (28.02.17 01:56) [9]

    > 1) a[] = 1 или a[Size(a)-1] = 1 автоматом добавляет элемент
    > в конец массива и увеличивает его Size\Length на еденицу.
    >

    Увеличение при каждом "чихе" на едИницу не очень есть оптимально. Ибо приводит к излишне частому перераспределению памяти, а в ряде случаев может привести и к слишком сильной фрагментации памяти. Из-за чего приложение более не сможет работать.
    Поэтому TList при необходимости увеличения размера списка увеличивает его не на едИницу, а на несколько большую величину.
    Так что присоединяюсь к сторонникам использования списков vs динамических массивов.
    P.S. Хотя, конечно, список - тот же самый динамический массив. Но уже готовый к употреблению. :)
  • Kilkennycat © (28.02.17 03:17) [10]

    > Германн ©   (28.02.17 01:56) [9]

    Использование списков или дин.массивов всё-таки зависит от: а) конкретной задачи; б) наличия того или иного (в с# с динамическими массивами несколько туговато).
  • dmk © (28.02.17 06:18) [11]
    Вячеслав   (27.02.17 12:27) [7]
    Лучше свой класс написать. У меня так например сделано:


    const
     MinBlockSize = 100;

    procedure TPObject.AddPoint(P: TPoint);
    begin
     //Добавляем память блоками
     if (FNumPoints mod MinBlockSize) = 0 then
     begin
       SetLength(FPoints, FNumPoints + MinBlockSize);
     end;
     Inc(FNumPoints);
     FPoints[FNumPoints - 1] := P;
    end;


    Чтобы ускорить добавляю память блоками.
    По одному элементу может стать затратно по производительности.
    Менеджер памяти каждый раз создает новый блок и переписывает данные в него.
    На массиве в 10000 элементов уже "тормоза" заметны в вашем случае с одним элементом.
 
Конференция "Начинающим" » Динамические массивы и SetLength [D7]
Есть новые Нет новых   [119544   +53][b:0][p:0.001]