![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как скопировать один массив массивов в другой?
AKE © (2010-07-02 19:12:00)сабж.
Sapersky (2010-07-04 17:29:00) [1]Копипаст "простых и эффективных" решений тоже сомнительное благо - при этом легко ляпнуть идиотскую ошибку и потом долго её искать.
Истина, видимо, посередине, с отклонениями (по вкусу) в ту или иную сторону.
Конкретно TypInfoEx затраченных на неё усилий не оправдала (кроме той части, которая относится к массивам), получился скорее хакерский концепт-юнит, чем "рабочая лошадка". Но если уж написано - то почему бы не воспользоваться. По крайней мере, для многомерных массивов и пр. сложных структур; хотя и для одномерных SetLength(B,Length(B)) куда больше смахивает на шаманское заклинание, чем UniqueData.
Демо (2010-07-04 15:31:00) [2]
> Sapersky (04.07.10 15:18) [34]
Универсализм - враг эффективности и простоты кода.
Sapersky (2010-07-04 15:18:00) [3]В случае автора (массив массивов) после присваивания оператор
SetLength(B,Length(B));
надо заменить на что-то вроде
SetLength(B,Length(B),Length(B[0]));
Я для таких случаев написал функцию UniqueData, по аналогии с UniqueString.
http://sapersky.narod.ru/files/TypInfoEx.rar
Демо (2010-07-04 14:23:00) [4]
> > С этого момента A указывает на старый массив, B - на новый.
> Это не строки и операция COPY-ON-WRITE не применима к ним,
> к ним применим только счетчик ссылок, по обнулению массив
> освобождается
Весь цимус в использованиии SetLength. SetLength выделяет под массив память и копирует туда данные из исходного массива.
При этом ссылка на массив становится уникальной.
PS.
Статические же массивы возможно копировать только в случае идентичности типов. Ни о какой различной размерности целевого исходного массива речи быть не может.
Sha (2010-07-04 12:07:00) [5]> Демо © (03.07.10 16:53) [11]
> Как для динамических, так и для статических массивов, достаточно выполнить:
> B := A;
> для динамического массива, кроме этого, нужно ещё выполнить
> SetLength(B,Length(B));
Небольшое добавление.
В случае автора (массив массивов) после присваивания оператор
SetLength(B,Length(B));
надо заменить на что-то вроде
SetLength(B,Length(B),Length(B[0]));
Здесь предполагается, что динамический массив двумерный и прямоугольный.
Anatoly Podgoretsky (2010-07-04 11:52:00) [6]> Германн (04.07.2010 03:00:28) [28]
А ты налей два литра в литровую тару.
Anatoly Podgoretsky (2010-07-04 11:50:00) [7]> Юрий Зотов (04.07.2010 01:50:24) [24]
> С этого момента A указывает на старый массив, B - на новый.
Это не строки и операция COPY-ON-WRITE не применима к ним, к ним применим
только счетчик ссылок, по обнулению массив освобождается
> Unlike strings and static arrays, COPY-ON-WRITE is not employed for
> dynamic arrays, so they are not automatically copied before they are
> written to.
> A[0] := 1;
> B := A;
> B[0] := 2;
> end;
> the value of A[0] is 2. (If A and B were static arrays, A[0] would still
> be 1.) и тоже для строк, A[1] будет иметь старое значение
> Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7)
> does not reallocate the array.
Anatoly Podgoretsky (2010-07-04 11:40:00) [8]> Германн (04.07.2010 01:44:23) [23]
Массив будет частично запонлнен, но массив А будет скопирован полностью.
Хуже если А > B, вот тогда капут.
В массиве будет M*M элементов и это число надо хранить, что бы можно было
работать с частично заполненым массивов. Вообще то это обычная ситуация,
когда размер массива больше, чем число элементов, правда обычно эту технику
используют для одномерных массивов.
Спрашивается нафиг это нужно, но ведь ранее не было динамических массивов,
люди не умееют работать с динамическими массивами, для преобразования
двумерного массива в одномерный, а работать с приведениями опять же не
умеем. Ну и т.д.
Германн (2010-07-04 03:00:00) [9]И при чём тут "объём" массива?
Германн (2010-07-04 02:56:00) [10]
> Демо © (04.07.10 02:52) [26]
>
>
> > Но что тогда будет после B:=A?
>
>
> Будет Incompatible types при компиляции.
Ну а я про что?
Демо (2010-07-04 02:52:00) [11]
> Но что тогда будет после B:=A?
Будет Incompatible typesпри компиляции.
Германн (2010-07-04 02:08:00) [12]
> Юрий Зотов © (04.07.10 01:50) [24]
>
> Не въезжаю, о чем спор?
>
>
Так ведь в начале были статические массивы.
Юрий Зотов (2010-07-04 01:50:00) [13]Не въезжаю, о чем спор?
B := A; // Копируется только указатель.
SetLength(B, Length(B)); // Создается реальная копия массива
С этого момента A указывает на старый массив, B - на новый. О каких утечках памяти идет речь?
Германн (2010-07-04 01:44:00) [14]
> Anatoly Podgoretsky © (03.07.10 13:42) [10]
>
> > Германн (03.07.2010 01:43:09) [9]
>
> Не обязательно, но копируемый массив должен быть такого
> же или меньшего
> объема.
>
Тогда возникает вопрос о "правильности" копирования.
Например массив A : array [0..N-1][0..N-1][0..N-1] of Byte меньше по объёму чем массив B : array [0..M-1][0..M-1] of Byte если N < 2/3 от M. Но что тогда будет после B:=A?
Anatoly Podgoretsky (2010-07-03 19:47:00) [15]> Демо (03.07.2010 18:12:21) [21]
Ну тогда другое дело.
Демо (2010-07-03 18:12:00) [16]
> особенно про A:=B;
Э-э... У меня написано B := A;
Anatoly Podgoretsky (2010-07-03 18:07:00) [17]А ты тоже повнимательнее читай, особенно про A:=B; Если после то это особо жестоко, это тянет на пожизненый эцик с гвоздями
Демо (2010-07-03 17:50:00) [18]
> Anatoly Podgoretsky © (03.07.10 17:25) [15]
Анатолий,Ю я бы советовал всё же внимательнее читать, то, что пишут.
У меня написано в [11], что SetLength должен выполняться после присвоения.
Демо (2010-07-03 17:47:00) [19]
> Jeer © (03.07.10 17:16) [12]
> > Демо © (03.07.10 16:53) [11]Иди покури "травку", прежде
> чем советовать.
Бредить не надо? Ок?
> Amoeba_ (03.07.10 17:18) [14]
> > Демо © (03.07.10 16:53) [11]> для динамического массива,
> кроме этого, нужно ещё выполнить> > SetLength(B,Length(B));
> Не надо.Читаем справку:If X and Y are variables of the same
> dynamic-array type, X :=Y points X to the same array as
> Y. (There is no need to allocate memory for X before performing
> this operation.)
При присвоении переменных динамических массивов происходит копирование ссылки на массив.
+ Рекомендую перечитать справку по SetLength.
procedure TForm1.btnCopyDinArraysClick(Sender: TObject);
type
TTestArr = array of byte;
var
vB1: TTestArr;
vB2: TTestArr;
begin
SetLength(vB1, 3);
vB1[0] := 1;
vB1[1] := 2;
vB1[2] := 3;
vB2 := vB1;
SetLength(vB2, Length(vB2)); //Здесь память будет перераспределена и все элементы скопированы.
vB1[0] := 10;
end;
Jeer (2010-07-03 17:27:00) [20]P.S.
Возможно, что средства управления динамическими массивами действительно "подчистят" B, но я не уверен.
Потому это не небрежность, а ошибка.