객체 메모리 할당 및 재활용 정보
여기에 dl 레지스터를 배치하는 것에 대한 아이디어가 있는 사람이 있는지 모르겠습니다. 그렇지 않은 경우 생각해 보면 괜찮을 것입니다. 사실 다음 코드(1) 앞에 이런 코드 MOV dl, 1이 있는데 왜 이렇게 된 걸까요? 그 이유는 그다지 간단하지 않은 코드 재사용입니다. 여기에서 dl 레지스터의 사용에 대해서는 Delphi 도움말에 소개되어 있습니다. 인내심을 갖고 직접 찾아보시면 마스터가 될 것입니다. 이것은 물고기를 구하는 것이 아니라 물고기 잡는 법을 배우는 것입니다. 볼랜드는 "나는 플래그를 저장하기 위해 dl 레지스터를 사용한다. 값이 1이면 객체를 생성할 것이다. 그렇지 않으면 객체를 생성하지 않을 것이다. 조금 헷갈리면 다시 생각해 보라"고 말했다. 다시. 아직 눈을 뜨지 않았다면 다음 코드 (2)를 보세요, 못 찾았다고 하지 마세요, 기침, 무슨 일이세요, 계속 말도 안 되는 소리를 하고 있습니다, 말하지 않겠다고 약속합니다 다시.
{코드(1)
테스트 DL, DL
jz +$08
ESP 추가, -$10
@ClassCreate로 전화하세요 }
{///코드(2)
PRocedure Tapplication.CreateForm(InstanceClass: TComponentClass; var 참조);
var
인스턴스: TComponent;
시작하다
//////// 인스턴스 := TComponent(InstanceClass.NewInstance);
TComponent(참조) := 인스턴스;
노력하다
//////// Instance.Create(Self);
제외하고
TComponent(참조) := nil;
들어올리다;
끝;
if (FMainForm = nil) 및 (인스턴스가 TForm) then
시작하다
TForm(Instance).HandleNeeded;
FMinForm := TForm(인스턴스);
끝;
끝;
}
즉, 델파이는 생성된 클래스의 인스턴스가 처음 호출될 때 코드 (1)을 호출합니다. 그러다가 누군가 Create 메소드를 호출해야 한다면 저는, 아니, 컴파일러일 뿐입니다. 이 MOV dl과 같습니다. 0, 코드 (1)의 판단 0 점프 명령이 가야 할 곳으로 이동하도록 합니다. (왜 또 말도 안 되는 소리를 합니까? 지난번에 약속합니다.) 실제로 여기의 Create 메소드는 단지 일반 메서드 및 , Create 메서드 또는 NewInstance 메서드에 대한 첫 번째 호출은 이 메시지를 보내는 클래스라는 점도 알아야 합니다. Windows 메시지, 이 메시지는 다른 메시지가 아닙니다. 하하, 또 말도 안되는 소리입니다. 정말 마지막입니다. 여기 메시지를 이해하지 못한다면 객체지향 및 모델링에 대한 지식을 주의깊게 배우고 호출하십시오. Create 메소드는 확립된 객체입니다. Instance.Create(Self)에 대해 생각해 보십시오. 물론 dl 레지스터의 값이 변경되었습니다.
좋아요, 시간이 별로 없어요. 마지막으로 깃발에 관해 추가하고 싶습니다. 이 dl 레지스터의 사용 지침을 보면 변경 사항이 없을 것이라고 말해야 합니다. 잘 생각해보면 델파이는 1에서 6까지 변경되지 않았습니다. 그런데 이는 델파이의 HB 디자이너가 물론 비교할 수는 없습니다. 하하, 또 가네요. 알겠습니다. 그만 얘기하겠습니다. 아, 마지막으로 TObject.Create 메소드는 결코 빈 메소드가 아니라는 점을 말씀드리고 싶습니다. 기억하고 생각해 보세요.
좋아요, 다른 것들은 직접 가서 보시길 바랍니다. 그러면 얻는 것이 많을 것입니다.
"여기서 나가세요. 보고 싶고 생각하고 싶고 당신의 말도 안되는 소리는 원하지 않습니다!" 누군가 웃고있었습니다! :)
안녕
컴파일러가 객체에 메모리를 할당할 때 제공되는 지원은 생성자를 호출하기 전에 다음 어셈블리 코드 줄을 삽입하는 것입니다.
테스트 DL, DL
jz +$08
ESP 추가, -$10
@ClassCreate 호출 // 이 코드 줄에 주의하세요.
위 코드의 마지막 줄은 system.pas 파일의 8949번 줄에서 _ClassCreate 함수를 호출합니다(Delphi 6에 따라 다름). 이 함수는 각 개체에 대해 적절한 메모리를 구체적으로 할당합니다. 메모리 할당이 완료된 후 클래스 생성자가 호출되어 데이터 멤버를 초기화합니다. 그 후에 컴파일러는 다음 어셈블리 코드 줄을 삽입합니다.
테스트 DL, DL
jz +$0f
@AfterConstruction에 전화하세요
팝 dWord ptr fs:[$00000000]
esp 추가, $0c
주요 작업은 각 개체 인스턴스의 AfterConstruction을 호출하는 것입니다. 이 호출은 C++Builder용으로 예약되어 있습니다.
마찬가지로, 객체를 소멸시킬 때 클래스의 소멸자를 먼저 호출하여 객체가 요청한 리소스를 해제해야 합니다. 그 후, 객체 자체가 차지하는 메모리 공간은 소멸자를 호출한 후 컴파일러가 다음 어셈블리 코드를 삽입하여 완료됩니다.
@BeforeDestruction으로 전화하세요
테스트 DL, DL
jle +$05
@ClassDestroy로 전화하세요
이러한 코드에 의해 수행되는 작업은 주로 system.pas의 8997행에서 _ClassDestroy 함수를 호출하여 객체를 구성하고 메모리를 할당할 때 수행되는 작업에 해당합니다.
생성자와 소멸자
생성자를 정의하려면 Constructor 키워드를 사용합니다. 일반적으로 생성자의 이름은 Create입니다(물론 다른 이름을 사용할 수도 있지만 이는 결코 좋은 디자인이 아닙니다!). 좋다:
유형
TMyFamily = class // 가족에 대해 정의된 클래스
사적인
FMyFatherName : String // 아버지의 이름;
FMyMotherName : String // 어머니의 이름;
… // 다른 가족 구성원
공공의
생성자 Create(strFatherName, strMotherName : String);
…… // 다른 방법
끝;
내 클래스에 생성자를 제공하지 않으면 해당 객체를 만들 수 있는지 물어볼 수 있습니다. 대답은 다음과 같습니다. 그렇습니다. 그 이유는 앞서 언급했듯이, 객체 자체가 차지하는 메모리 할당은 컴파일러에 의해 완료됩니다. 그리고 오브젝트 파스칼에서는 모든 클래스(TObject 클래스 자체 제외)가 TObject 클래스에서 파생되므로 컴파일러는 TObject.Create() 생성자를 호출하지만 이 함수는 빈 함수이므로 TMyFamily 클래스에 영향을 주지 않습니다. 데이터 멤버(FMyFatherName, FMyMotherName)가 초기화되면 TObject.Create()가 아버지나 어머니를 전혀 모르기 때문에 자동으로 빈 문자열(예: '')로 지워집니다.
객체를 생성할 때 생성자는 다음 형식으로 직접 호출됩니다.
MyFamilyObject := TMyFamily.Create('장', '리');
소멸자를 정의하려면 Destructor 키워드를 사용합니다. 규칙에 따라 소멸자의 이름은 Destroy입니다. 좋다:
유형
TMyClass = 클래스
공공의
소멸자 파괴();
끝;
소멸자 선언 끝에 override 문을 추가하는 이유는 다형성의 경우 객체가 올바르게 소멸될 수 있도록 하기 위한 것입니다(다형성에 대해서는 섹션 2.4에서 자세히 설명합니다). override 키워드를 추가하지 않으면 컴파일러는 "'Destroy' 메서드가 기본 유형 'TObject'의 가상 메서드를 숨깁니다"와 유사한 경고를 표시합니다. 경고는 정의한 Destroy가 기본 클래스의 가상 메소드 TObject.Destroy()를 숨긴다는 의미입니다. 이 경우 객체는 다형성 상황에서 올바르게 소멸될 수 없습니다.
참고: 소멸자는 재정의 문을 사용하여 선언해야 합니다.
마찬가지로, 클래스에서 해제해야 하는 특별한 리소스가 없으면 소멸자를 정의할 필요가 없습니다. 그러나 객체를 소멸시킬 때는 Destroy()를 직접 호출하는 대신 객체의 Free() 메서드를 호출해야 합니다.
MyFamilyObject.Free();
이는 Free() 메소드가 객체 자체가 nil인지 판단하고, nil이 아닌 경우 안전성을 높이기 위해 객체의 Destroy()를 호출하기 때문입니다. 이제 이 작업을 수행하는 더 안전한 방법이 있으므로 수행하지 않을 이유가 없습니다.
참고: 개체에 대해 Destroy()를 직접 호출하지 말고 대신 Free()를 호출하세요.
이를 통해 오브젝트 파스칼에서는 객체가 적용한 리소스의 할당 및 해제에만 주의하면 되고 객체 자체가 차지하는 공간에는 신경 쓸 필요가 없다는 결론을 내릴 수 있습니다.