“Weak reference”: down to earth explanation needed

后端 未结 4 375
暗喜
暗喜 2021-02-04 03:17

Can someone provide an explanation of a weak reference in Delphi?

I noticed that the concept is often mentioned in some library/framework source code I scrutini

4条回答
  •  后悔当初
    2021-02-04 03:51

    Instances that reference each other by interface references keep each other alive in a reference count based interface implementation.

    A weak reference is used to break the "keep each other alive" bear hug. This is done by declaring one reference as a pure pointer to circumvent the reference counting mechanism.

    IFriend = Interface(IInterface)
    end;
    
    TFriend = class(TInterfacedObject, IFriend)
    private
      FFriend: IFriend;
    end;
    
    
    var
      Peter: IFriend;
      John: IFriend;
    begin
      Peter := TFriend.Create;
      John := TFriend.Create;
    
      Peter.Friend := John;
      John.Friend := Peter;
    end;
    

    Even when Peter and John go out of scope, their instances are kept around because their mutual reference keeps their refcount from dropping to zero.

    The problem is more commonly found in composite patterns (parent - child relationships) where the child has a back reference to the parent:

    ISomething = Interface(IInterface)
    end;
    
    TSomething = class(TInterfacedObject, ISomething)
    end;
    
    TParent = class(TSomething)
      FChildren: TInterfacedList;
    end;
    
    TChild = class(TSomething)
      FParent: ISomething;
    end;
    

    Again, parent and child can keep eachother around because their mutual reference keeps their refcount from dropping to zero.

    This is solved with a weak reference:

    TChild = class(TSomething)
      FParent: Pointer;
    end;
    

    By declaring the FParent as a "pure" pointer the reference counting mechanism doesn't come into play for the back reference to the parent. When a parent goes out of scope, its reference count now can drop to zero because its children no longer keep its ref count above zero.

    Note This solution does require careful attention to lifetime management. Children can be kept alive beyond the life time of the parent when something on the "outside" of these classes keeps a reference to a child. And this can lead to all sorts of interesting AV's when the child assumes the parent reference always points to a valid instance. If you need it, make sure that when the parent goes out of scope, it makes the children nil their back references before it nils its own references to its children.

提交回复
热议问题