Конференция "Начинающим" » Передача параметра
 
  • VOsipov © (23.04.17 10:51) [0]
    Объясните пожалуйста, я не понимаю простых вещей.

    Если передать в процедуру MyProc(Str: String), то Str во внешней процедуре не меняется. Если так: MyProc(var Str: String), то Str - изменится. Это понятно.

    Но почему если передать в MyProc(MyLabel: TLabel) компонент, то все изменения в этой процедуры повлияют на него, ведь передаем же не так: MyProc(var MyLabel: TLabel) ??
  • Плохиш © (23.04.17 12:39) [1]
    MyLabel ссылка на экземпляр класса, переменную менять нельзя, но поля класса на который она указывает менять никто не запрещает.

    PS. В документации всё подробно описано.
  • Rouse_ © (23.04.17 12:41) [2]

    > Если передать в процедуру MyProc(Str: String), то Str во
    > внешней процедуре не меняется.

    Потому что передается копия строки.


    > Если так: MyProc(var Str: String), то Str - изменится.

    Потому что передается по ссылке, считай указатель на строку.

    А объект "MyLabel: TLabel" так-же является указателем, делай выводы.
  • VOsipov © (23.04.17 13:17) [3]

    > Rouse_ ©   (23.04.17 12:41) [2]


    Спасибо, но почему передается указатель на объект, а не копия объекта?
  • rrrrrr (23.04.17 14:48) [4]
    потому что он большой и не является непрерывным куском памяти в общем случае.
    попробуй передай еще
  • rrrrrr (23.04.17 14:51) [5]
    это если еще не вдаваться в смысл передачи копии объекта.
    точнее в полное отсутствие какого бы то ни было смысла такой передачи
  • Rouse_ © (23.04.17 21:22) [6]

    > VOsipov ©   (23.04.17 13:17) [3]
    >
    > > Rouse_ ©   (23.04.17 12:41) [2]
    >
    >
    > Спасибо, но почему передается указатель на объект, а не
    > копия объекта?

    Потому что это указатель, вот было бы MyProc(var MyLabel: TLabel), тогда был бы указатель на указатель
  • Игорь Шевченко © (23.04.17 21:43) [7]

    > почему передается указатель на объект, а не копия объекта?


    Так устроено. В книжках, опять же, все написано и даже с картинками.
  • Германн © (24.04.17 01:45) [8]

    > VOsipov ©   (23.04.17 13:17) [3]
    > Спасибо, но почему передается указатель на объект, а не
    > копия объекта?

    А нафига нужно в данном случае делать "копию объекта"? Хоть один разумный и достаточный довод попробуй придумать.
  • ухты © (24.04.17 04:57) [9]

    > Хоть один разумный и достаточный довод попробуй придумать.
    а какой "разумный и достаточный" при передачи, например, вещественного числа? и чем он "разумнее" нежели для объекта?
  • rrrrr © (24.04.17 08:31) [10]
    когда число, то нас интересует его значение. ничего другого у числа нет.
    оно и передается по значению. хотя можно и по ссылке.

    теперь попробуй скажи что такое "значение объекта"
  • Sha © (24.04.17 10:51) [11]
    1. С одной стороны, передача объекта без var может дать микроскопическое увеличение скорости и позволит защитить указатель от изменений, которые без надобности и так никто в здравом уме делать не будет.
    2. С другой стороны, в последствии замена объекта на record приведет к ошибке в работе программы.
    3. С третьей стороны, наличие var может ввести читателя в заблуждение.

    В общем, на мой взгляд, вопрос не такой однозначный как кажется.
  • Игорь Шевченко © (24.04.17 11:35) [12]
    Sha ©   (24.04.17 10:51) [11]


    > С другой стороны, в последствии замена объекта на record
    > приведет к ошибке в работе программы


    И правильно сделает. Мне крайне трудно представить себе серьезную программу, в которой бездумно меняют class на record и обратно, при этом забывая о всех последствиях такой замены.
    Вопрос однозначный - есть синтаксис языка, нравится он или не нравится, это  личные предпочтения каждого, но придерживаться синтаксиса стоит.
  • D7 (24.04.17 11:37) [13]
    > Спасибо, но почему передается указатель на объект, а не копия объекта?

    Вам как-то не так объяснили. Передаётся как раз копия.
    Вот только сам по себе TLabel это не объект, а указатель на объект. И передаётся копия значения TLabel. А значение TLabel это указатель.
  • Sha © (24.04.17 11:38) [14]
    > Игорь Шевченко ©   (24.04.17 11:35) [12]

    к сожалению, в последнее время мне часто приходится осмысленно менять class на record и обратно в серьезной программе, при этом не забывая о всех последствиях такой замены )
  • Игорь Шевченко © (24.04.17 11:44) [15]
    Sha ©   (24.04.17 11:38) [14]

    Вряд ли ты это делаешь бездумно :)
  • NoUser © (24.04.17 14:02) [16]
    > не понимаю простых вещей.

    Тут, наверное, многие их не понимают ;)

    В 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 18:43) [17]

    > когда число, то нас интересует его значение. ничего другого
    > у числа нет.

    а у объекта кроме объекта еще что то есть?
    а реф по валуе тайпу это для красоты придуман?
  • rrrrrr © (24.04.17 19:20) [18]
    а у объекта кроме объекта еще что то есть?
    а реф по валуе тайпу это для красоты придуман?


    ты если собрался передать объект по значению,
    то сначала придумай что такое значение объекта.
    а уж потом со своей красотой умничай.
  • KSergey © (25.04.17 11:01) [19]
    > Германн ©   (24.04.17 01:45) [8]
    > А нафига нужно в данном случае делать "копию объекта"? Хоть один разумный и достаточный довод попробуй придумать.

    Полегче бы в формулировках, господа.

    Например, в С++ передаётся именно копия объекта, как и любые другие типы.
    Так что разумный довод - объекты ничем не хуже других типов.
    Но Дельфи устроена иначе, имеет право.
  • KSergey © (25.04.17 11:04) [20]
    > rrrrr ©   (24.04.17 08:31) [10]
    > теперь попробуй скажи что такое "значение объекта"

    Тоже самое, что и "что такое значение record.
    Которое - вдруг - передаётся как раз по значению в Delphi.
  • rrrrr © (25.04.17 11:12) [21]
    физически как это выглядит.
    через какие регистры, стек, и так далее.
    и что именно передается когда "объект пердается по значению"
  • sniknik © (25.04.17 12:44) [22]
    > Тоже самое, что и "что такое значение record.
    обьект это скорее Trecord, а не record, всегда динамический, в отличие от "plain" переменных, т.что сравнение не корректно.
  • KSergey © (25.04.17 14:01) [23]
    > sniknik ©   (25.04.17 12:44) [22]
    > > Тоже самое, что и "что такое значение record.
    > обьект это скорее Trecord, а не record, всегда динамический,
    >  в отличие от "plain" переменных, т.что сравнение не корректно.

    Не понимаю что тут некорректного.
    Экземпляр объекта - это набор полей, ничего другого в экземпляре нет.
    Как и в record

    Другое дело, что в дельфи это принципиально разделили.
  • rrrrr © (25.04.17 14:29) [24]
    ничего другого в экземпляре нет.

    ладно, будем считать что методы ты не заметил.

    берем объект с сотней свойств.
    начинай передавать их по значению.
    точнее не их а его, объект.
  • Игорь Шевченко © (25.04.17 14:55) [25]

    > ладно, будем считать что методы ты не заметил.


    методы от экземпляра объекта разве зависят ?
  • rrrrr © (25.04.17 14:56) [26]
    так и свойства не очень от объекта зависят.
    особенно задекларированные выше по иерархии.

    ну так передаст тут кто-нибудь наконец хоть один объект по значению?
    а то чото упираются что передать можно, но не показывают как это
  • sniknik © (25.04.17 15:26) [27]
    > Экземпляр объекта - это набор полей, ничего другого в экземпляре нет.
    > Как и в record
    record весь в памяти программы, как и integer например, у обьекта в программе только указатель, а поля и т.д. в отдельно выделенной памяти. принципиальная разница. а вот указатель на record, т.е. Trecord по именованию в дельфе, это уже похоже, тот же указатель в программе, и "тело" в выделенной памяти.
    а то что оба содержат набор полей дело десятое... ну вот не скажешь же, что машина и катер это одно и тоже, только на том основании, что у обоих сиденья внутри... или скажешь?
  • Игорь Шевченко © (25.04.17 17:06) [28]

    > ну так передаст тут кто-нибудь наконец хоть один объект
    > по значению?
    > а то чото упираются что передать можно, но не показывают
    > как это


    Чего ты хочешь увидеть ? Набор ассемблерных команд ? Сам не сумеешь что ли посмотреть ?
  • Игорь Шевченко © (25.04.17 17:10) [29]
    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

  • rrrrr © (25.04.17 17:11) [30]
    Сам не сумеешь что ли посмотреть ?

    конечно сумею посмотреть.
    но когда мне покажут семантику передачи объекта "по значению"

    вообще конечно мне это нафик не сдалось.

    но просто кто-то здесь с так упорствует на тему что передать можно и что ничего дурного в этом нет, что просто уже хочется посмотреть на такой вызов.

    на передачу объекта по значению.
  • rrrrr © (25.04.17 17:13) [31]
    TForm1.Bar(AO: TB);

    это не интересно.
    это передается по значению ссылка на объект.

    мне же хочется увидеть передачу объекта по значению.
  • Игорь Шевченко © (25.04.17 17:18) [32]

    > это передается по значению ссылка на объект.


    А в вызванной процедуре делается копия.

    Тебе какая разница, где копия будет создана с точки зрения Object Pascal - вызываемая функция явно на паскале копии не создает, все изменения внутри функции будут применены к копии, оригинальный экземпляр объекта не изменится. В чем собственно и смысл передачи по значению.
  • rrrrr © (25.04.17 17:30) [33]
    да пофик что там в процедуре делается.

    передай сразу по значению.
    чтобы копия создалась только в силу вызова процедуры.
  • Игорь Шевченко © (25.04.17 17:35) [34]

    > передай сразу по значению.


    Это платная услуга
  • rrrrr © (25.04.17 17:37) [35]
    да я у же как бы понял.
  • Sha © (25.04.17 17:58) [36]
    > Плохиш ©   (23.04.17 12:39) [1]
    > MyLabel ссылка на экземпляр класса, переменную менять нельзя,
    > но поля класса на который она указывает менять никто не запрещает.

    > Rouse_ ©   (23.04.17 12:41) [2]
    > А объект "MyLabel: TLabel" так-же является указателем, делай выводы.

    > VOsipov ©   (23.04.17 13:17) [3]
    > Спасибо, но почему передается указатель на объект, а не копия объекта?


    вот так дискуссия плавно ушла от экземпляров класса к экземплярам объектов
  • Игорь Шевченко © (25.04.17 18:29) [37]

    > вот так дискуссия плавно ушла от экземпляров класса к экземплярам
    > объектов


    Ты видишь разницу ? Я - нет. Рудимент в виде object рассматривать несерьезно :)
 
Конференция "Начинающим" » Передача параметра
Есть новые Нет новых   [118439   +24][b:0][p:0.003]