2017-11-24 8 views
2

델파이에서 동적 배열이 참조 카운트 된 경우 참조 카운터가 시각적 구성 요소와 함께 작동하는 것처럼 시각적 구성 요소를 배열에 저장하는 것이 안전합니까? 시각적 구성 요소가 일반 비 시각 코드와 많이 다르므로 참조 카운터를 속일 수 있습니까?동적 배열에 시각적 구성 요소를 저장하는 것이 안전합니까?

델파이의 최신 복사본에서 동적 배열이 참조 카운팅보다 다른 방식으로 메모리 관리되는지 모르겠습니다. 장면은 일종의 List로 구현됩니다.

답변

3

이것은 완전히 안전합니다. 시각적 구성 요소는 인스턴스 변수가 처리되는 방식과 관련하여 비 시각적 구성 요소와 전혀 다르지 않습니다.

동적 배열의 참조 계산은 단순히 배열의 자동 메모리 관리로 간주 할 수 있습니다. 내가 "배열에 대해"말했음을 주목하라. 동적 배열의 참조 계산은 해당 요소의 메모리 관리에 대해 아무런 의미가 없습니다.

TMyVisualComponent의 동적 배열 요소는 단순히 개체에 대한 참조를 보유하는 변수입니다. TMyVisualComponent 유형의 로컬 변수 또는 TMyVisualComponent 유형의 필드와 다르지 않습니다.

는 다음의 두 가지 예를 고려 FObj

type 
    TMyClass1 = class 
    private 
    FObj: TMyVisualComponent; 
    end; 

    TMyClass2 = class 
    private 
    FArr: TArray<TMyVisualComponent>; 
    end; 

는 그 수명이 다른 관리되는 인스턴스에 대한 참조가 배치된다. 마찬가지로 FArr에는 수명이 다른 여러 인스턴스에 대한 참조가 배치됩니다.

TMyClass1의 인스턴스가 삭제되면 FObj이 나타내는 인스턴스에는 아무런 변화가 없습니다. 모든 일이 발생하면 TMyClass1의 인스턴스가 파괴되고 변수 FObj이 포함되어 있으므로 해당 변수도 파괴됩니다. 나는 "변수"라고 말했다. 변수 FObj이 파기되면 참조하는 개체가 영향을받지 않습니다.

마찬가지로 TMyClass2의 인스턴스가 삭제되면 FArr 배열이 삭제되지만 해당 개체가 참조하는 개체에는 아무런 영향이 없습니다.

마지막 주름 하나가 ARC 컴파일러에서 클래스에 대한 모든 참조는 참조 횟수입니다. 위에서 말한 내용은 TMyVisualComponent 인스턴스의 참조 카운팅을 포함하도록 수정해야합니다. 그러나 이들 인스턴스에 대한 참조를 보유하고있는 다른 당사자가 TMyVisualComponent이기 때문에 전체적으로 계속 살아있을 것입니다.

요약하면 TArray<TMyVisualComponent>을 같은 범위에서 정의한 TMyVisualComponent의 여러 변수 이상으로 간주하면됩니다.

+0

VCL이 Windows에서만 작동하므로 VCL 구성 요소가 ARC 컴파일러에 존재하지 않는다고 추가 할 수 있습니다. – Johan

+0

@Johan 질문에 VCL 또는 FMX가 없습니다. –

2

델파이의 제한된 요소 집합 만 참조 횟수입니다.
VCL 구성 요소가 아닙니다. 그들은 참조 계산 방식으로 자동으로 파괴되지 않습니다. VCL 구성 요소를 참조하는 대신 ownership이라는 개념을 사용합니다. VCL 구성 요소의 소유자는 자신이 소유 한 모든 구성 요소를 파괴해야합니다.

VCL 구성 요소를 동적 또는 기타 배열로 저장하는 것이 안전합니다.

동적 배열은 D4에서 소개 된 이후의 배열과 동일합니다.힙에 할당 된 간단한 배열로서 참조 횟수입니다.

항목을 포함하는 배열이 참조 개수라는 ​​사실은 어떤 식 으로든 항목에 영향을 미치지 않습니다. 더 많은 항목을 저장하면 배열의 refcount가 이 아닌이됩니다. 당신은, 배열에 대한 참조의 수를 증가과 같이 경우에만 상승 : 동적 배열의 참조 카운트 항목을 저장할 경우, 자신의 refcount는 감소됩니다

function Test: TArray<TComponent>; 
var 
    a: TArray<TComponent> 
begin 
    SetLength(a, 100); //first use of a, refcount = 1 
    a[0]:= Button1; //nothing happens 
    Result:= a; //increases refcount of a to 2. 
end; //end of scope for a, refcount of a decreased to 1. 

procedure Test2; 
var 
    x: TArray<TComponent> 
begin 
    x:= Test; //x = Test.a, refcount of x = 1 
    x[1]:= Button2; //nothing happens 
end; //end of scope for x, refcount = 0, x is freed. 
//nothing happens to button1 and button2, because VCL components are not reference counted. 

(을 파괴하는 것은 그 자신의 refcount가를 제공하는 경우 0) 동적 배열이 파괴 될 때. Refcounted 유형은 다음과 같습니다

  • 문자열
  • 동적 배열 ARC 컴파일러에서
  • 인터페이스
  • 클래스 (모바일, 리눅스)

주 (예, 당신이 둥지 그들이 할 수있는) 당신 동안 VCL 클래스에 대한 인터페이스 참조를 얻으면 VCL 클래스의 refcount는 -1로 고정됩니다 (_Addref_Release은 더미 메소드입니다. 아무것도).

+0

이해하기 어려운 개념은 Test2에서는 배열이 사라졌지만 배열의 일부로 Button을 만든 경우 인간의 마음은 배열을 버튼 구조를 저장하는 것으로 간주합니다. 버튼은 여전히 ​​사용중인 화면에 있지만 아직 저장되어있는 배열은 파괴되어 무효 한 버튼을 만드는 것처럼 보이지만 Windows OS가 버튼을 차지하고 버튼이 실제로 저장되지 않기 때문에 무효가 아닙니다. 배열에서, 그리고 개체는 단지 포인터입니다. TArray 과 TComponent의 배열의 차이점을 조사해야합니다 : < > Generics – Programmz

+0

'type TArray = TComponent의 배열'과 같은 소리가납니다. 하지만 더 나은 이유는'TArray '는 유형이 x 일 때 동적 배열 인'x 배열 '과 열린 배열 매개 변수로서'x의 배열'을 혼동하지 않기 때문입니다. Tbutton은 아직 그것을 포함하고있는 폼이 소유하고 있기 때문에 참조가 없다. – Johan