На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (495) « Первая ... 165 166 [167] 168 169 ...  494 495  ( Перейти к последнему сообщению )  
> Delphi vs C++ vs C# , ну и Java немножко, где-то ближе к старшему байту номеров страниц
    Цитата Qraizer @
    Думаю, компилятор вместо передачи указателя на фрейм внешней функции явно обращается ровно на один фрейм выше. Или заюзал оптимизацию "подавления указателей на стековые фреймы". Или ещё чего, мало ли причин можно придумать.

    Компилятор тут кагбэ и не приделах, т.к. он даже и не в курсе, что переданный нетипизированный указатель - это указатель на локальную процедуру, в ином случае сразу бы получили "Local procedure/function 'UseLocalVar' assigned to procedure variable".

    Цитата Qraizer @
    Любопытно было бы посмотреть в листинг.

    Да, тут есть такой нюанс, если в контексте локальной процедуры используются переменные, объявленные в родительской процедуре
    ExpandedWrap disabled
      procedure ParentProc;
      var
        N: Integer;
       
        procedure LocalProc;
        begin
          Inc(N);
        end;
       
      begin
        LocalProc;
      end;


    То перед её вызовом в стек добавляется указатель на текущий (родительской процедуры) кадр стека, по которому в дальнейшем, в контексте локальной процедуры, будут вычисляться адреса переменных.
    ExpandedWrap disabled
      LocalProc;

    ExpandedWrap disabled
      push ebp ;сохраняется указатель на кадр стека
      call LocalProc
      pop ecx

    в контексте локальной процедуры:
    ExpandedWrap disabled
      Inc(N);

    ExpandedWrap disabled
      mov eax,[ebp+$08] ;по смещению от указателя на кадр стека локальной процедуры вычисляется указатель на кадр стека родительской процедуры
      inc dword ptr [eax-$04] ;теперь относительно указателя на кадр стека можно получить все адреса переменных

    Этот же принцип действует и для рекурсивных вызовов самой локальной процедуры.

    Цитата D_KEY @
    Что мешает "локальным функциям" действовать также, как лямбдам?

    Возможно дело просто в реализации? ;)

    Цитата D_KEY @
    Локальные процедуры могли бы действовать также.

    Во первых: а смысл? А во вторых: локальные процедуры тогда бы на порядок потеряли в скорости выполнения.

    Цитата MyNameIsIgor @
    Я то надеялся, что тут будет, например, DesweR и подхватит знамя "убогой объектной системы" - хоть какая-то движуха.

    DesweR не читает советских газет :tong:

    Добавлено
    Цитата korvin @
    кстати, что-то вспомнилось АОП. допустим нам нужно, чтобы для объектов какого-то класса (и его потомков) перед или после выполнения какого-то метода происходили какие-то действия (запись в лог или что-то такое). причем классы эти могут быть не наши (т.е. изменить их определение может быть невозможным). как поступить в топиковых языках? дополнительно: если это нужно добавить ко всем объектам (в делфи и C# корень один, а в его нет, потому и вопрос)?

    Для C# можно сказать решение готово, читал эту статью на хабре, для Delphi надо подумать...
    Сообщение отредактировано: DesweR -
      Цитата korvin @
      кстати, что-то вспомнилось АОП. допустим нам нужно, чтобы для объектов какого-то класса (и его потомков) перед или после выполнения какого-то метода происходили какие-то действия (запись в лог или что-то такое). причем классы эти могут быть не наши (т.е. изменить их определение может быть невозможным). как поступить в топиковых языках? дополнительно: если это нужно добавить ко всем объектам (в делфи и C# корень один, а в его нет, потому и вопрос)?

      Для С++ через "добавление" чего-то перед вызовом и после, пожалуй нельзя. Если только активно не используется "шаблонный метод", да или просто нет открытых виртуальных функций - в этом случае, все уже почти готово. В качестве общего решения можно было бы предложить работать через специальный указатель(выполняющий запись в лог до и после любого обращения к объекту) и/или обертку, реализующую интерфейс класса...

      Добавлено
      Цитата DesweR @
      Цитата D_KEY @
      Локальные процедуры могли бы действовать также.

      Во первых: а смысл? А во вторых: локальные процедуры тогда бы на порядок потеряли в скорости выполнения.

      1) смысл в том, чтобы локальные функции были удобным инструментом, а не странным, зависимым от реализации механизмом, сомнительной пользы.
      2) ну да, пожалуй для языков без сборки мусора с этим все несколько сложнее. Приходится или копировать данные, или вручную отслеживать ссылки. В С++ можно все организовать через shared_ptr'ы, но в этом случае мы используем динамическую память "на ровном месте", практически без необходимости.
      Кстати, как у вас лямбды захватывают контекст?
        Цитата D_KEY @
        Кстати, как у вас лямбды захватывают контекст?

        вроде уже обсуждали, в дельфи - лямбды - это неявные объекты, реализующие интерфейс. читай, тот же самый приплюснутый shared_ptr.

        А локальные процедуры были введены в паскаль(НЕ object pascal) задолго до того как появились интерфейсы.
          Цитата D_KEY @
          1) смысл в том, чтобы локальные функции были удобным инструментом, а не странным, зависимым от реализации механизмом, сомнительной пользы.

          Так они и так удобный инструмент, ни больше ни меньше :)
          А если нужна передача вовне - к услугам анонимные методы.

          Цитата D_KEY @
          Кстати, как у вас лямбды захватывают контекст?

          Сейчас точно не посмотрю, захватывают переменные по ссылкам, а не по значению. К слову, управление временем жизни захваченного контекста реализовано посредством интерфейсного объекта.
            Цитата DesweR @
            Цитата D_KEY @
            Кстати, как у вас лямбды захватывают контекст?

            Сейчас точно не посмотрю, захватывают переменные по ссылкам, а не по значению.

            А если они после захвата уничтожаются в создающем лямбду коде, но продолжают использоваться в том месте, куда была отдана лямбда?

            Цитата
            К слову, управление временем жизни захваченного контекста реализовано посредством интерфейсного объекта.

            Ну да. Подсчет ссылок.
              Цитата D_KEY @
              А если они после захвата уничтожаются в создающем лямбду коде, но продолжают использоваться в том месте, куда была отдана лямбда?

              Если ты уничтожаешь объект сам явно - то скорее всего задни AV (проверить сейчас не на чем).
                Цитата DesweR @
                Компилятор тут кагбэ и не приделах, т.к. он даже и не в курсе, что переданный нетипизированный указатель - это указатель на локальную процедуру, в ином случае сразу бы получили "Local procedure/function 'UseLocalVar' assigned to procedure variable".
                Ну так об этом и спрашивал. Уже понял.
                Просто какая-то нестыковка. Во вашим словам получается, что использовать их всё-таки нельзя, а у народа вон получилось. Плюс к этому, как я смотрю по листингу, проблемы в общем-то нет. Точнее, есть:
                Цитата DesweR @
                Возможно дело просто в реализации?
                но точно такая же, как и у нас. Я уже D_KEY-ю говорил: если контект определения сущности, на которую ссылаемся, жив, то всё работает на ура, если же уже мёртв, то ссылка оказывается висячей в нивочто. И проблема как раз в том, что определить, какая ситуация из этих двух сейчас имеет место быть, в общем случае невозможно. У нас есть полуавтоматические shared_ptr/weak_ptr, но полностью автоматического решения представить не могу, если честно.
                Цитата jack128 @
                А локальные процедуры были введены в паскаль(НЕ object pascal) задолго до того как появились интерфейсы.
                Задолго до того, как появлись процедурные типы. Так точнее.
                Сообщение отредактировано: Qraizer -
                  Цитата Qraizer @
                  если контект определения сущности, на которую ссылаемся, жив, то всё работает на ура, если же уже мёртв, то ссылка оказывается висячей в нивочто. И проблема как раз в том, что определить, какая ситуация из этих двух сейчас имеет место быть, в общем случае невозможно.

                  ИМХО, проблема в языках, которые не могут обеспечить нужное время жизни объекта...
                  Если для С++ на это есть причины, то какие причины у такого языка, как Delphi, который изначально ориентирован на область прикладного программирования? Или это просто наследство?

                  Цитата
                  У нас есть полуавтоматические shared_ptr/weak_ptr, но полностью автоматического решения представить не могу, если честно.

                  Да, думаю что его нет. Кстати, как я понял, интерфейсы в Delphi также обеспечивают подсчет ссылок и могут в данном случае использоваться как наши shared_ptr и weak_ptr.
                  Кстати, есть ли какой-то аналог последнего(weak_ptr) в Delphi?
                    Цитата Qraizer @
                    Просто какая-то нестыковка. Во вашим словам получается, что использовать их всё-таки нельзя, а у народа вон получилось.

                    У такого "народа", не сомневаюсь, получится и объекты использовать после их уничтожения. Кто их заставляет вместо процедурных типов использовать нетипизированные указатели или отключать "Typed @ operator"?

                    Цитата Qraizer @
                    И проблема как раз в том, что определить, какая ситуация из этих двух сейчас имеет место быть, в общем случае невозможно.

                    Если писать в соответствии с руководством по языку, то таких проблем вообще не возникнет.

                    Цитата D_KEY @
                    Кстати, есть ли какой-то аналог последнего(weak_ptr) в Delphi?

                    Воспроизводится легко. А вообще, это смотря какая задача, грамотный дизайн может и исключить потребность в weak_ptr.
                    Сообщение отредактировано: DesweR -
                      Цитата DesweR @
                      Если писать в соответствии с руководством по языку, то таких проблем вообще не возникнет.
                      Этточно. Ни ошибок компиляции, ни отладки.
                        Цитата DesweR @
                        У такого "народа", не сомневаюсь, получится и объекты использовать после их уничтожения. Кто их заставляет вместо процедурных типов использовать нетипизированные указатели или отключать "Typed @ operator"?

                        Вот, наконец-то вы начинаете понимать и "классическую" нашу аргументацию :)

                        Цитата
                        Цитата D_KEY @
                        Кстати, есть ли какой-то аналог последнего(weak_ptr) в Delphi?

                        Воспроизводится легко. А вообще, это смотря какая задача, грамотный дизайн может и исключить потребность в weak_ptr.

                        Можно узнать, как воспроизводится?
                        Относительно дизайна, думаю, что ты не прав. Иногда нужно иметь ссылку на объект, но не являться одним из его "владельцев". Это касается даже языков со сборкой мусора, примеры уже приводились. Правда ситуаций таких немного.
                          Цитата D_KEY @
                          Можно узнать, как воспроизводится?

                          А как захочешь :)
                          ExpandedWrap disabled
                            type
                              ISharedPtr = interface //наш абстрактный SharedPtr
                                procedure SomeProc; //якобы объект которым владеет SharedPtr
                              end;
                             
                              TSharedPtr = class(TInterfacedObject, ISharedPtr)
                              public
                                destructor Destroy; override;
                                function   IsAlive: Boolean; //если счетчик ссылок > 0 то True
                                procedure  SomeProc;
                              end;
                             
                             
                              TWeakPtr = record
                              strict private
                                FObj: TSharedPtr;
                                function GetObj: TSharedPtr;
                              public
                                procedure Init(const AObj: ISharedPtr);
                                property Obj: TSharedPtr read GetObj;
                              end;
                             
                             
                            destructor TSharedPtr.Destroy;
                            begin
                              Writeln('SharedPtr.Destroy');
                            end;
                             
                            function TSharedPtr.IsAlive: Boolean;
                            begin                  
                              Result := (FRefCount > 0);
                            end;
                             
                            procedure TSharedPtr.SomeProc;
                            begin
                              Writeln('SharedPtr.SomeProc');
                            end;
                             
                             
                            procedure TWeakPtr.Init(const AObj: ISharedPtr);
                            begin
                              //объект не увеличивает счетчик ссылок интерфейса
                              FObj := (AObj as TSharedPtr);
                            end;
                             
                            function TWeakPtr.GetObj: TSharedPtr;
                            begin
                              Result := nil;
                              
                              if FObj.IsAlive then
                                Result := FObj
                              else
                                raise Exception.Create('WeakPtr: SharedPtr is destroyed');
                            end;
                             
                             
                            var
                              Intf: ISharedPtr;
                              WeakPtr: TWeakPtr;
                            begin
                              try
                                Intf := TSharedPtr.Create;
                                WeakPtr.Init(Intf);
                             
                                Intf.SomeProc;
                                WeakPtr.Obj.SomeProc;
                                Intf := nil; //уничтожаем SharedPtr
                                WeakPtr.Obj.SomeProc;
                              except
                                on E: Exception do
                                  Writeln(E.Message);
                              end;
                              ReadLn;
                            end.

                          ExpandedWrap disabled
                            SharedPtr.SomeProc
                            SharedPtr.SomeProc
                            SharedPtr.Destroy
                            WeakPtr: SharedPtr is destroyed
                            DesweR

                            если шаредПтр уже уничтожен, то как же ты можешь обращаться к его методу IsAlive ??


                            D_KEY
                            а как WeakPtr в cpp реализован??
                            Сообщение отредактировано: jack128 -
                              Цитата jack128 @
                              D_KEY
                              а как WeakPtr в cpp реализован??

                              Он тесно связан с shared_ptr, его можно получить только из shared_ptr'а. Сам объект, которым мы владеем удалится, как только на него не будет активных ссылок(shared_ptr), а вот запись, хранящая счетчики не удаляется, пока не останется ссылок на эту запись(т.е. учитывается и weak_ptr). Таким образом на объект хранятся два счетчика - один для подсчета ссылок на объект(и когда он обнуляется происходит удаление объекта), другой для подсчета ссылок на саму запись об этом объекте(когда обнуляется он, происходит удаление этой записи).
                              Думаю, в реализациях есть какие-то оптимизации, но концептуально это происходит так.
                              Сообщение отредактировано: D_KEY -
                                D_KEY
                                а. Ну тогда никаких принципиальных проблем для аналогичной реализации в дельфи - нет.

                                Добавлено
                                ExpandedWrap disabled
                                  IRefCounter<T: class> = interface
                                    procedure AddShared;
                                    procedure ReleaseShared; //  когда FSharedCount = 0 - уничтожаем объект и isAlive = false. ВНИМАНИЕ - это НЕ RefCount, который в TInterfacedObject'е сидит, а отдельный счетчик
                                    
                                    function IsAlive: Integer;
                                    fucntion GetValue: T;
                                  end;
                                   
                                  ISharedPtr<T: class> = interface
                                    function GetValue: T;
                                    property Value: T read GetValue;
                                  end;
                                   
                                  TSharedPtr<T: class> = class(TInterfacedObject, ISharedPtr<T>)
                                  private
                                    FCounter: IRefCounter;
                                  protected
                                    function _AddRef: Integer; // FCounter.AddShared
                                    function _Release: Integer; // fCounter.ReleaseShared;
                                  public
                                    constructor Create(AValue: T); // fCounter := TRefCounter<T>.Create(AVAlue);
                                  end;
                                   
                                   
                                  IWeakPtr<T: class> = interface
                                    function GetValue: T;
                                    property Value: T read GetValue;
                                    function IsAlive: boolean;
                                  end;
                                   
                                  TWeakPtr<T: class> = class(TInterfacedObject, IWeakPtr<T>)
                                  private
                                    FCounter: IRefCounter<T>;
                                  protected
                                    function GetValue: T; // fCounter.GetValue;
                                    function IsAlive: boolean; // fCounter.IsAlive;
                                  public
                                    constructor Create(AValue: ISharedPtr<T>); // fCounter := (AValue as TSharedPtr<T>).FCounter;
                                  end;
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (495) « Первая ... 165 166 [167] 168 169 ...  494 495


                                Рейтинг@Mail.ru
                                [ Script execution time: 0.2945 ]   [ 14 queries used ]   [ Generated: 31.07.26, 16:10 GMT ]