Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 07.08.2008, 10:42
dmdx dmdx вне форума
Начинающий
 
Регистрация: 24.05.2008
Адрес: Москва
Сообщения: 133
Репутация: 15
Вопрос Помогите разобраться с типизированными ссылками

Всем доброго настроения. Народ! помогите немного разобраться с типизированными ссылками.
Например:
Код:
type
 PPerson = ^TPerson;
 TPerson = record
  Name: AnsiString;
  Age: byte;
end;

var
 Per1: TPerson;
 Per2: PPerson;

begin
 Per1.Name:='Peter'; // первый случай

 New(Per2);            // Второй случай
 Per2.Name:='Peter'; 
 Despose(Per2);
end;

В первом случае программа выделяет место в памяти при запуске и обращается непосредственно к переменным (данным). И если надо передать другой похожей переменной передает данные содержщиеся в переменной. Если я правильно понял.?!

Во втором случае программа выделяет память для работы и затем соответственно освобождает её (динамическая память). И работает уже не с переменными а с адресом памяти где находятся данные переменной. И если надо передать другой похожей переменной передает адрес памяти где находиться данные.?!

Получается что если работать со строками и структурами лучше использовать типизированые ссылки? т.к. передавать данные на обработку выгоднее и быстрее передать адрес где находятся данные.

И в чем плюсы и минусы этих ссылок.?

Спасибо за внимание.

Последний раз редактировалось dmdx, 07.08.2008 в 10:45.
Ответить с цитированием
  #2  
Старый 07.08.2008, 12:24
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Смотря, что понимать под обработкой? Кстати, ANSI строки в случае копирования вовсе не копируются, а у них увеличивается счётчик использования (как у интерфейсов). В случае ОБЪЕКТОВ (class) Delphi предоставляет удобный интерфейс, например, операции со свойствами выглядят как применение переменных, хотя при этом вызываются методы. Сам объект - это не область памяти (структура), а ссылка на неё. А раньше приходилось писать ^ или @. Что делать, если одна функция меняет данные, а другая хочет их удалить? Тут надо делать копии. При передаче массива в подпрограмму, стоит var или нет, весь массив не передаётся, а только адрес первого элемента. В Си дошли до того, что используют двойные указатели, т.е. указатель не на объект, а на адрес, а в Delphi всё выглядит посимпатичнее.

Последний раз редактировалось AlexSku, 07.08.2008 в 12:29.
Ответить с цитированием
  #3  
Старый 07.08.2008, 15:52
dmdx dmdx вне форума
Начинающий
 
Регистрация: 24.05.2008
Адрес: Москва
Сообщения: 133
Репутация: 15
По умолчанию

А разве в Delphi есть разница между объявлением переменной String и AnsiString? Нет но я понимаю что это два разных типа. но помойму если в переменную String поместить строку длинной более 255 символов она автоматом становиться AnsiString. Или по крайней мере я точно впихивал строку длинной 1608 символов в переменную String.
__________________
Програмист приходит на стрельбище. Стреляет. Прапор смотрит на мешень и говорит
Прапор: вы не попали ни один раз.
Программист: Пули вылетели, проблемы у вас.
Ответить с цитированием
  #4  
Старый 08.08.2008, 01:19
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,034
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну не совсем так.
В Delphi тип String является псевдонимом, по умолчанию указывающем на AnsiString. Что бы сделать Pascal-строку надо явно указать ее длинну (String[100], например).

Теперь по поводу типизированных указателей.
Вообще, когда в процедуру передается переменная по var, то ВСЕГДА передается указатель. Это раз.
Два. Раньше, до 32-битной ОС, была существенная разница в использовании типа и указателя, т.к. память в случае указателя выделялась в "куче", что позволяло использовать более 64К данных. Сейчас разницы в принципе нет, за исключением того, что используя "грязное" преобразование типов можно рассматривать данные в памяти через различные структуры, что юывает иногда очень нужно (чаще всего в API Windows). Ну и хранить типизпрованные указатели можно в TList (хотя я давно перешел на TObjectList и работаю с объектами, имея не только преимущество использования указателей, но и все прелести ООП).
Ответить с цитированием
  #5  
Старый 08.08.2008, 08:45
dmdx dmdx вне форума
Начинающий
 
Регистрация: 24.05.2008
Адрес: Москва
Сообщения: 133
Репутация: 15
По умолчанию

Вроде как немного разобрался.
__________________
Програмист приходит на стрельбище. Стреляет. Прапор смотрит на мешень и говорит
Прапор: вы не попали ни один раз.
Программист: Пули вылетели, проблемы у вас.
Ответить с цитированием
  #6  
Старый 08.08.2008, 14:03
dmdx dmdx вне форума
Начинающий
 
Регистрация: 24.05.2008
Адрес: Москва
Сообщения: 133
Репутация: 15
По умолчанию

Код:
var: Fl: TextFile;

procedure OpenFile(var FilePatch: string);
begin
 try
  AssignFile(Fl,FilePatch);
  Reset(Fl);
 finally
 end;
end;

begin
OpenFile('c:\log.log');
end;

т.е. по логике я передаю функции OpenFile адрес памяти в которой храниться значение c:\log.log !?
А если не использовать var

Код:
...
procedure OpenFile(FilePatch: string);
...

то я бы передавал именно значение c:\log.log !?
__________________
Програмист приходит на стрельбище. Стреляет. Прапор смотрит на мешень и говорит
Прапор: вы не попали ни один раз.
Программист: Пули вылетели, проблемы у вас.
Ответить с цитированием
  #7  
Старый 08.08.2008, 15:05
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,034
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну, в общем случае, да.

Можешь проверить такой фокус:
Код:
procedure VarTest(var A : String);
begin
  A := 'VarTest';
  ShowMessage(A);
end;

procedure NotVarTest(A : String);
begin
  A := 'NotVarTest';
  ShowMessage(A);
end;

var
  B : String;
begin
  B := 'Main';
  ShowMessage(B);
  VarTest(B);
  ShowMessage (B);

  B := 'Main';
  ShowMessage(B);
  NotVarTest(B)
  ShowMessage(B);
end;

И посмотри что выводится.
Ответить с цитированием
  #8  
Старый 08.08.2008, 17:05
dmdx dmdx вне форума
Начинающий
 
Регистрация: 24.05.2008
Адрес: Москва
Сообщения: 133
Репутация: 15
По умолчанию

Интересная картина получается. Если использовать var в процедурах то передовать можно только переменные. Прямой текст (данные) передавать нельзя.

Код:
прокатит

procedure TForm1.Button1Click(Sender: TObject);
 procedure GetText(Text: string);
 begin
  Edit1.Text:=Text;
 end;
var
 r: string;
begin
 r:='Welcome';
 GetText(r);
end;

не прокатит

procedure TForm1.Button1Click(Sender: TObject);
 procedure GetText(Text: string);
 begin
  Edit1.Text:=Text;
 end;
begin
 GetText('welcome');
end;

и ещё один плюс процедура с использованием var в машинном коде занимает менюше места и соответственно выполняется быстрее.
файлик with_out_var без использования var в процедуре
Код:
procedure TForm1.Button1Click(Sender: TObject);
 procedure GetText(Text: string);
 begin
  Edit1.Text:=Text;
 end;
var
 r: string;
begin
 r:='Welcome';
 GetText(r);
end;

файлик with_var c использования var в процедуре
Код:
procedure TForm1.Button1Click(Sender: TObject);
 procedure GetText(var Text: string);
 begin
  Edit1.Text:=Text;
 end;
var
 r: string;
begin
 r:='Welcome';
 GetText(r);
end;

и наглядно видно что asm операторов меньше с использованием var. это наверное обуславливается тем что. при запуске процы без var переменная text создается, а проца с var истолькует в себе глобальную переменную!?
Изображения
Тип файла: jpg with_out_var.JPG (97.2 Кбайт, 3 просмотров)
Тип файла: jpg with_var.JPG (85.7 Кбайт, 3 просмотров)
__________________
Програмист приходит на стрельбище. Стреляет. Прапор смотрит на мешень и говорит
Прапор: вы не попали ни один раз.
Программист: Пули вылетели, проблемы у вас.
Ответить с цитированием
  #9  
Старый 08.08.2008, 18:36
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,034
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Разница в том, что без использования var значение переменной помещается в стек, а при использовании var - нет. Вот и разница. По сути, не заморачивался бы ты этими вопросами, т.к. реальна разница имеет влияние на грани погрешности измерения

Лучше помни одну вещь - при использовании var-параметров у тебя может возникать сторонний эффект, т.е. изменяется значение переданной переменной. Лучше этого избегать.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 23:44.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter