-
Объясните пожалуйста, я не понимаю простых вещей.
Если передать в процедуру MyProc(Str: String), то Str во внешней процедуре не меняется. Если так: MyProc(var Str: String), то Str - изменится. Это понятно.
Но почему если передать в MyProc(MyLabel: TLabel) компонент, то все изменения в этой процедуры повлияют на него, ведь передаем же не так: MyProc(var MyLabel: TLabel) ??
-
MyLabel ссылка на экземпляр класса, переменную менять нельзя, но поля класса на который она указывает менять никто не запрещает.
PS. В документации всё подробно описано.
-
> Если передать в процедуру MyProc(Str: String), то Str во > внешней процедуре не меняется.
Потому что передается копия строки.
> Если так: MyProc(var Str: String), то Str - изменится.
Потому что передается по ссылке, считай указатель на строку.
А объект "MyLabel: TLabel" так-же является указателем, делай выводы.
-
> Rouse_ © (23.04.17 12:41) [2]
Спасибо, но почему передается указатель на объект, а не копия объекта?
-
потому что он большой и не является непрерывным куском памяти в общем случае. попробуй передай еще
-
это если еще не вдаваться в смысл передачи копии объекта. точнее в полное отсутствие какого бы то ни было смысла такой передачи
-
> VOsipov © (23.04.17 13:17) [3] > > > Rouse_ © (23.04.17 12:41) [2] > > > Спасибо, но почему передается указатель на объект, а не > копия объекта?
Потому что это указатель, вот было бы MyProc(var MyLabel: TLabel), тогда был бы указатель на указатель
-
> почему передается указатель на объект, а не копия объекта?
Так устроено. В книжках, опять же, все написано и даже с картинками.
-
> VOsipov © (23.04.17 13:17) [3] > Спасибо, но почему передается указатель на объект, а не > копия объекта?
А нафига нужно в данном случае делать "копию объекта"? Хоть один разумный и достаточный довод попробуй придумать.
-
> Хоть один разумный и достаточный довод попробуй придумать. а какой "разумный и достаточный" при передачи, например, вещественного числа? и чем он "разумнее" нежели для объекта?
-
когда число, то нас интересует его значение. ничего другого у числа нет. оно и передается по значению. хотя можно и по ссылке.
теперь попробуй скажи что такое "значение объекта"
-
1. С одной стороны, передача объекта без var может дать микроскопическое увеличение скорости и позволит защитить указатель от изменений, которые без надобности и так никто в здравом уме делать не будет. 2. С другой стороны, в последствии замена объекта на record приведет к ошибке в работе программы. 3. С третьей стороны, наличие var может ввести читателя в заблуждение.
В общем, на мой взгляд, вопрос не такой однозначный как кажется.
-
Sha © (24.04.17 10:51) [11]
> С другой стороны, в последствии замена объекта на record > приведет к ошибке в работе программы
И правильно сделает. Мне крайне трудно представить себе серьезную программу, в которой бездумно меняют class на record и обратно, при этом забывая о всех последствиях такой замены. Вопрос однозначный - есть синтаксис языка, нравится он или не нравится, это личные предпочтения каждого, но придерживаться синтаксиса стоит.
-
> Спасибо, но почему передается указатель на объект, а не копия объекта?
Вам как-то не так объяснили. Передаётся как раз копия. Вот только сам по себе TLabel это не объект, а указатель на объект. И передаётся копия значения TLabel. А значение TLabel это указатель.
-
> Игорь Шевченко © (24.04.17 11:35) [12]
к сожалению, в последнее время мне часто приходится осмысленно менять class на record и обратно в серьезной программе, при этом не забывая о всех последствиях такой замены )
-
Sha © (24.04.17 11:38) [14]
Вряд ли ты это делаешь бездумно :)
-
> не понимаю простых вещей.
Тут, наверное, многие их не понимают ;)
В MyProc(Str: String), MyProc(const Str: String) и MyProc(var Str: String)
строки передаются одинаково, а именно, как указатель на указатель (адрес по которому размещён адрес первого элемента строки).
Разница в действиях с параметром Str определяется самой MyProc.
Например, в MyProc(Str: String) перед явным изменением Str, будет создан ёё дубликат, в котором и произойдут изменения.
Такой внутренний 'механизм' используется для длинных строк и может ввести в заблуждение относительно поведения других типов данных в сходных условиях.
( > Но почему если передать в MyProc(MyLabel: TLabel) компонент, то все изменения в этой процедуры повлияют на него, ведь передаем же не так: MyProc(var MyLabel: TLabel) ?? )
Для экземпляров объектного типа дублирования не характерно.
Но мы сами можем прописать/выполнить необходимые для этого действия (создать новый и наполнить/скопировать в него нужные данные).
Например для ситуации, если у нас есть объект-шаблон, на основании которого должны выполнить дальнейшие вычислении, не изменяя при этом сам шаблон.
-
> когда число, то нас интересует его значение. ничего другого > у числа нет.
а у объекта кроме объекта еще что то есть? а реф по валуе тайпу это для красоты придуман?
-
а у объекта кроме объекта еще что то есть? а реф по валуе тайпу это для красоты придуман?
ты если собрался передать объект по значению, то сначала придумай что такое значение объекта. а уж потом со своей красотой умничай.
-
> Германн © (24.04.17 01:45) [8] > А нафига нужно в данном случае делать "копию объекта"? Хоть один разумный и достаточный довод попробуй придумать.
Полегче бы в формулировках, господа.
Например, в С++ передаётся именно копия объекта, как и любые другие типы. Так что разумный довод - объекты ничем не хуже других типов. Но Дельфи устроена иначе, имеет право.
-
> rrrrr © (24.04.17 08:31) [10] > теперь попробуй скажи что такое "значение объекта"
Тоже самое, что и "что такое значение record. Которое - вдруг - передаётся как раз по значению в Delphi.
-
физически как это выглядит. через какие регистры, стек, и так далее. и что именно передается когда "объект пердается по значению"
-
> Тоже самое, что и "что такое значение record. обьект это скорее Trecord, а не record, всегда динамический, в отличие от "plain" переменных, т.что сравнение не корректно.
-
> sniknik © (25.04.17 12:44) [22] > > Тоже самое, что и "что такое значение record. > обьект это скорее Trecord, а не record, всегда динамический, > в отличие от "plain" переменных, т.что сравнение не корректно.
Не понимаю что тут некорректного. Экземпляр объекта - это набор полей, ничего другого в экземпляре нет. Как и в record
Другое дело, что в дельфи это принципиально разделили.
-
ничего другого в экземпляре нет.
ладно, будем считать что методы ты не заметил.
берем объект с сотней свойств. начинай передавать их по значению. точнее не их а его, объект.
-
> ладно, будем считать что методы ты не заметил.
методы от экземпляра объекта разве зависят ?
-
так и свойства не очень от объекта зависят. особенно задекларированные выше по иерархии.
ну так передаст тут кто-нибудь наконец хоть один объект по значению? а то чото упираются что передать можно, но не показывают как это
-
> Экземпляр объекта - это набор полей, ничего другого в экземпляре нет. > Как и в record record весь в памяти программы, как и integer например, у обьекта в программе только указатель, а поля и т.д. в отдельно выделенной памяти. принципиальная разница. а вот указатель на record, т.е. Trecord по именованию в дельфе, это уже похоже, тот же указатель в программе, и "тело" в выделенной памяти. а то что оба содержат набор полей дело десятое... ну вот не скажешь же, что машина и катер это одно и тоже, только на том основании, что у обоих сиденья внутри... или скажешь?
-
> ну так передаст тут кто-нибудь наконец хоть один объект > по значению? > а то чото упираются что передать можно, но не показывают > как это
Чего ты хочешь увидеть ? Набор ассемблерных команд ? Сам не сумеешь что ли посмотреть ?
-
type
TB = object
public
Foo1: Integer;
Foo2: Integer;
function Sum: Integer;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
procedure Bar (AO: TB);
end;
procedure TForm1.Bar(AO: TB);
var
Value: Integer;
begin
Value := AO.Sum;
ShowMessageFmt('%d', [Value]);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
B: TB;
begin
B.Foo1 := 1;
B.Foo2 := 2;
Bar(B);
end;
Выливается в это:
(FormCreate)
000016FA C7 45 F8 01 00 00 00 mov dword ptr [ebp+0FFFFFFF8h],000000001h
00001701 C7 45 FC 02 00 00 00 mov dword ptr [ebp+0FFFFFFFCh],000000002h
00001708 8D 55 F8 lea edx,[ebp+0FFFFFFF8h]
0000170B 8B C6 mov eax,esi
0000170D E8 4E FF FF FF call main.TForm1.Bar
main.TForm1.Bar:
00001660 55 push ebp
00001661 8B EC mov ebp,esp
00001663 83 C4 F0 add esp,0FFFFFFF0h
00001666 56 push esi
00001667 57 push edi
00001668 8B F2 mov esi,edx
0000166A 8D 7D F8 lea edi,[ebp+0FFFFFFF8h]
0000166D A5 movsd
0000166E A5 movsd
0000166F 8D 45 F8 lea eax,[ebp+0FFFFFFF8h]
00001672 E8 E1 FF FF FF call main.TB.Sum
00001677 89 45 F0 mov [ebp+0FFFFFFF0h],eax
0000167A C6 45 F4 00 mov byte ptr [ebp+0FFFFFFF4h],000h
0000167E 8D 55 F0 lea edx,[ebp+0FFFFFFF0h]
00001681 33 C9 xor ecx,ecx
00001683 B8 9C 16 40 00 mov eax,00040169Ch
00001688 E8 37 FB FF FF call ShowMessageFmt
0000168D 5F pop edi
0000168E 5E pop esi
0000168F 8B E5 mov esp,ebp
00001691 5D pop ebp
00001692 C3 ret
-
Сам не сумеешь что ли посмотреть ?
конечно сумею посмотреть. но когда мне покажут семантику передачи объекта "по значению"
вообще конечно мне это нафик не сдалось.
но просто кто-то здесь с так упорствует на тему что передать можно и что ничего дурного в этом нет, что просто уже хочется посмотреть на такой вызов.
на передачу объекта по значению.
-
TForm1.Bar(AO: TB);
это не интересно. это передается по значению ссылка на объект.
мне же хочется увидеть передачу объекта по значению.
-
> это передается по значению ссылка на объект.
А в вызванной процедуре делается копия.
Тебе какая разница, где копия будет создана с точки зрения Object Pascal - вызываемая функция явно на паскале копии не создает, все изменения внутри функции будут применены к копии, оригинальный экземпляр объекта не изменится. В чем собственно и смысл передачи по значению.
-
да пофик что там в процедуре делается.
передай сразу по значению. чтобы копия создалась только в силу вызова процедуры.
-
> передай сразу по значению.
Это платная услуга
-
да я у же как бы понял.
-
> Плохиш © (23.04.17 12:39) [1] > MyLabel ссылка на экземпляр класса, переменную менять нельзя, > но поля класса на который она указывает менять никто не запрещает.
> Rouse_ © (23.04.17 12:41) [2] > А объект "MyLabel: TLabel" так-же является указателем, делай выводы.
> VOsipov © (23.04.17 13:17) [3] > Спасибо, но почему передается указатель на объект, а не копия объекта?
вот так дискуссия плавно ушла от экземпляров класса к экземплярам объектов
-
> вот так дискуссия плавно ушла от экземпляров класса к экземплярам > объектов
Ты видишь разницу ? Я - нет. Рудимент в виде object рассматривать несерьезно :)
|