Форум: "Начинающим";
Текущий архив: 2010.02.21;
Скачать: [xml.tar.bz2];
ВнизКак работает знак := для рекордов? Найти похожие ветки
← →
yantux © (2009-12-19 14:41) [0]Правильно ли я понимаю, что если переменные a и b типа рекорд, то при a:=b; копируются значения всех полей b в a?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
type1 = record
i : integer;
f : extended;
end;
type2 = record
field : type1;
end;
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
LF1 = #13;
LF2 = #10;
var
Form1: TForm1;
t11, t12 : type1;
t21, t22 : type2;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
t11.i:=123;
t11.f:=456.789;
t12.i:=11;
t12.f:=22.33;
self.Memo1.Lines.Add("1: t11: i="+inttostr(t11.i)+" f="+floattostr(t11.f)+LF1+LF2);
self.Memo1.Lines.Add("2: t12: i="+inttostr(t12.i)+" f="+floattostr(t12.f)+LF1+LF2);
t12:=t11;
self.Memo1.Lines.Add("3: t11: i="+inttostr(t11.i)+" f="+floattostr(t11.f)+LF1+LF2);
self.Memo1.Lines.Add("4: t12: i="+inttostr(t12.i)+" f="+floattostr(t12.f)+LF1+LF2);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
self.Memo1.Lines.Clear;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
t21.field.i:=123;
t21.field.f:=456.789;
t22.field.i:=11;
t22.field.f:=22.33;
self.Memo1.Lines.Add("1: t21: i="+inttostr(t21.field.i)+" f="+floattostr(t21.field.f)+LF1+LF2);
self.Memo1.Lines.Add("2: t22: i="+inttostr(t22.field.i)+" f="+floattostr(t22.field.f)+LF1+LF2);
t22:=t21;
self.Memo1.Lines.Add("3: t21: i="+inttostr(t21.field.i)+" f="+floattostr(t21.field.f)+LF1+LF2);
self.Memo1.Lines.Add("4: t22: i="+inttostr(t22.field.i)+" f="+floattostr(t22.field.f)+LF1+LF2);
end;
end.
← →
Sapersky (2009-12-19 15:03) [1]Для записей с managed-полями (строки и т.п.) вызывается system._CopyRecord, которая корректно их копирует (с увеличением RefCount). Для простых - побайтное копирование, не очень хорошо помню, но вроде бы оно инлайнится, для мелких записей последовательность mov, для больших movsd/movsb.
Вообще такие вещи проверяются элементарно - ставьте брейк на копировании и жмите Ctrl-Alt-C.
← →
Омлет © (2009-12-19 15:04) [2]Правильно.
← →
yantux © (2009-12-21 11:31) [3]
> Для записей с managed-полями (строки и т.п.) вызывается
> system._CopyRecord, которая корректно их копирует (с увеличением
> RefCount). Для простых - побайтное копирование, не очень
> хорошо помню, но вроде бы оно инлайнится, для мелких записей
> последовательность mov, для больших movsd/movsb.Вообще такие
> вещи проверяются элементарно - ставьте брейк на копировании
> и жмите Ctrl-Alt-C.
что такое ref count?
← →
Sapersky (2009-12-21 13:15) [4]Счётчик ссылок, используется для автоматического уничтожения длинных строк, дин. массивов и пр. типов с управляемым временем жизни.
http://www.rsdn.ru/article/Delphi/dynarrays.xml
← →
yantux © (2009-12-21 15:55) [5]
> Счётчик ссылок, используется для автоматического уничтожения
> длинных строк, дин. массивов и пр. типов с управляемым временем
> жизни.
А зачем увеличиние RefCount, если по знаку := должно происходить копирование данных, а не ссылок на данные?
← →
RWolf © (2009-12-21 16:19) [6]очевидно, строки не копируются.
← →
yantux © (2009-12-21 17:12) [7]
> очевидно, строки не копируются.
т.е. тип string?
type
d = record
i : integer;
s : string;
end;
var
a, b : d;
begin
a:=b;
end.
В этом примере значение всех полей переменной b будen нормально будут нормально скопированы в переменную a, т.е. именно значения, а не ссылки на них. Тогда почему будет увеличиваться RefCount?
← →
Ega23 © (2009-12-21 17:15) [8]потому что string - это не совсем простой тип данных.
← →
RWolf © (2009-12-21 17:43) [9]
> RWolf © (21.12.09 16:19) [6]
> очевидно, строки не копируются.
Всё не так очевидно, вообще говоря. Попробуем посмотреть содержимое этих записей до и после копирования:procedure TForm1.Button1Click(Sender: TObject);
type
d = record
i : integer;
s : string;
end;
var
a, b : d;
function getaddr(const dd:d):string;
var p:^Cardinal;pc:PChar;
begin
p:=@dd;
Inc(p); //указывает на dd.s
Result:=IntToHex(p^,8);
p:=Pointer(p^); //указывает на собственно символы строки
pc:=PChar(p);
Result:=Result+" "+pc;
end;
begin
a.s:="asfdsadf";
b.s:="qweqwe";
ShowMessage(getaddr(a)+#13#10+getaddr(b));
a:=b;
ShowMessage(getaddr(a)+#13#10+getaddr(b));
end;
вот что получаем в результате:
до копирования a:=b
00452B7C asfdsadf
00452B90 qweqwe
после копирования a:=b
00953BD4 qweqwe
00452B90 qweqwe
т.е. имеем две копии строки в памяти.
← →
Sapersky (2009-12-21 18:53) [10]Это связано со специфической обработкой строковых констант. Если сделать так:
a.s := InttoStr(123); b.s := InttoStr(456);
то значения указателей будут равны.
Здесь должно быть расписано:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1206
← →
Leonid Troyanovsky © (2009-12-21 18:56) [11]
> RWolf © (21.12.09 17:43) [9]
> т.е. имеем две копии строки в памяти.
Не очень понятно, что, собс-но, исследуется.
Вот, например, количество ссылок:
type
d = record
i : integer;
s : string;
end;
type
PStrRec = ^StrRec;
StrRec = packed record
refCnt: Longint;
length: Longint;
end;
var
a, b : d;
procedure TForm1.Button1Click(Sender: TObject);
begin
a.i := GetTickCount;
a.s := IntToStr(a.i);
b := a;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Caption := IntToStr(PStrRec(PChar(a.s)-SizeOf(StrRec)).RefCnt);
end;
А убедиться, что b.s не копируется (а ссылается на a.s)
можно сравнив их адреса: Pointer(a.s) vs Pointer(b.s).
Т.е., имеем обычное copy-on-write .
--
Regards, LVT.
← →
RWolf © (2009-12-22 13:46) [12]
> Sapersky (21.12.09 18:53) [10]
Полезная статья, спасибо.
По прочтении осталось неясным, по какой причине в [9] после присвоения a:=b значение указателя на константную строку b.s не копируется в a.s, вместо этого создаётся новая строка, с тем же содержимым.
← →
Sapersky (2009-12-22 14:48) [13]Комментарий к system._LStrAsg:
"Literals [константы] are copied to prevent a situation where a dynamically
allocated DLL or package assigns a literal to a variable and then
is unloaded -- thereby causing the string memory (in the code
segment of the DLL) to be removed -- and therefore leaving the
global variable pointing to invalid memory."
← →
RWolf © (2009-12-22 15:39) [14][13]
да, пусть уж лучше создаётся копия :)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.02.21;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.005 c