О выделении и переработке объектной памяти
Не знаю, есть ли у кого-нибудь идеи по поводу размещения здесь регистра дл. Если нет, просто подумайте. Если подумаете, то все будет хорошо. На самом деле перед следующим кодом (1) стоит такая строка кода MOV dl,1, так почему же причина не очень простая, повторное использование кода. Что касается использования регистра dl, то в справке Delphi есть введение. Наберитесь терпения и поищите его сами. Если вы его найдете, вы станете мастером. Это учиться, нет, учиться ловить рыбу, а не просить рыбу. Борланд сказал следующее: «Я использую регистр dl для хранения флага. Если значение равно 1, то я создам объект. В противном случае я не буду создавать объект. Если вы немного запутались, подумайте об этом еще раз и». снова. Если вы еще не открыли глаза, то взгляните на следующий код (2), не говорите, что не нашли, кашель, что происходит, я продолжаю говорить чушь, обещаю не говорить этого снова.
{Код (1)
тест дл, дл
jz +$08
добавить особенно, -$10
позвоните @ClassCreate }
{///Код (2)
PROcedure Tapplication.CreateForm(InstanceClass: TComponentClass; var Reference);
вар
Экземпляр: TComponent;
начинать
//////// Экземпляр := TComponent(InstanceClass.NewInstance);
TComponent(Ссылка) := Экземпляр;
пытаться
//////// Instance.Create(Self);
кроме
TComponent (Ссылка) := ноль;
поднимать;
конец;
если (FMainForm = nil) и (Экземпляр — TForm), то
начинать
TForm(Экземпляр).HandleNeeded;
FMainForm := TForm(Экземпляр);
конец;
конец;
}
В данном случае, то есть Delphi вызывает код (1) при первом вызове экземпляра созданного класса. Затем, если кому-то и нужно вызвать метод Create, то мне, нет, это просто компилятор. вот такой MOV дл, 0, чтобы инструкция перехода суждения 0 в коде (1) перешла в то место, куда она должна идти (Почему вы снова несете ерунду? В последний раз, обещаю.) На самом деле метод Create здесь — это просто метод. обычный метод и , вы также должны заметить, что первый вызов метода Create или метода NewInstance — это класс, отправляющий это сообщение (обратите внимание, что это сообщение не является Сообщение Windows, это сообщение не другое, ха-ха, это снова ерунда, это действительно в последний раз, это правда. Если вы не понимаете это сообщение, пожалуйста, внимательно изучите знания объектно-ориентированного моделирования и моделирования) и позвоните. это позже. Метод Create — это установленный объект, Instance.Create(Self); подумайте об этом, конечно, значение регистра dl изменилось.
Хорошо, у меня мало времени. Наконец, я хотел бы добавить, что касается флага (тайваньский метод перевода, я думаю, что это слово хорошее, я предлагаю вам также использовать его, чтобы избавить меня от многих проблем позже) и в инструкции по использованию этого регистра dl следует сказать Никаких изменений не будет. Если хорошенько подумать, Delphi не менялся с 1 на 6. Кстати, это тоже доказывает, что HB-конструктор Delphi - это. характер. Конечно, я не могу сравнивать. Ха-ха, вот еще раз, ладно, я перестану говорить. Ну и, наконец, позвольте мне сказать, что метод TObject.Create ни в коем случае не пустой метод, запомните, а потом подумайте об этом.
Хорошо, другие вещи, пожалуйста, посмотрите их лично. В этом случае вы много выиграете.
«Уйди отсюда, я хочу это увидеть и подумать, и мне не нужна твоя чушь!» Кто-то смеялся! :)
пока
Когда компилятор выделяет память для объекта, он обеспечивает поддержку, заключающуюся в вставке этих строк ассемблерного кода перед вызовом конструктора:
тест дл, дл
jz +$08
добавить особенно, -$10
вызов @ClassCreate // Обратите внимание на эту строку кода
Последняя строка приведенного выше кода вызывает функцию _ClassCreate в строке 8949 файла system.pas (в зависимости от Delphi 6). Эта функция специально выделяет соответствующую память для каждого объекта. После завершения выделения памяти вызывается конструктор класса для инициализации членов данных. После этого компилятор вставит следующие строки ассемблерного кода:
тест дл, дл
jz +$0f
позвоните @AfterConstruction
pop dWord ptr fs:[$00000000]
добавить esp, $0c
Основная задача — вызвать AfterConstruction каждого экземпляра объекта. Этот вызов бесполезен в Delphi. Его существование зарезервировано для C++Builder.
Аналогично, при разрушении объекта сначала необходимо вызвать деструктор класса, чтобы освободить ресурсы, запрошенные объектом. После этого пространство памяти, занимаемое самим объектом, перерабатывается. Завершает эту работу компилятор, вставив после вызова деструктора следующий ассемблерный код:
позвони @BeforeDestruction
тест дл, дл
jle +$05
позвони @ClassDestroy
Работа, выполняемая этими кодами, соответствует тому, что делается при построении объекта и выделении памяти, главным образом при вызове функции _ClassDestroy в строке 8997 в system.pas.
Конструктор и деструктор
Чтобы определить конструктор, используйте ключевое слово Constructor. По соглашению имя конструктора — Create (конечно, можно использовать и другие имена, но это ни в коем случае не является хорошим дизайном!). нравиться:
тип
TMyFamily = class // Класс, определенный для вашей семьи.
Частный
FMyFatherName : String // имя вашего отца;
FMyMotherName : String // имя вашей матери;
… // Другие члены вашей семьи
Общественный
Конструктор Create(strFatherName, strMotherName: String);
…… // Другие методы
Конец;
Вы можете спросить: если я не предоставлю конструктор для своего класса, можно ли создать его объекты? Ответ: да. Причина была упомянута ранее: выделение памяти, занимаемой самим объектом, завершается компилятором. А поскольку в Object Pascal все классы (кроме самого класса TObject) являются производными от класса TObject, компилятор вызовет конструктор TObject.Create(), но эта функция является пустой функцией и на класс TMyFamily она не повлияет. . Когда элементы данных (FMyFatherName, FMyMotherName) инициализируются, они автоматически очищаются до пустых строк (т. е. ''), поскольку TObject.Create() вообще не знает вашего отца или матери!
При создании объекта конструктор вызывается напрямую, в следующем виде:
MyFamilyObject := TMyFamily.Create('Чжан', 'Ли');
Используйте ключевое слово Destructor для определения деструктора. По соглашению деструктор называется Destroy. нравиться:
тип
ТМиКласс = класс
Общественный
Переопределение деструктора Destroy();
Конец;
Причина, по которой оператор переопределения добавляется в конец объявления деструктора, заключается в том, чтобы гарантировать, что объект может быть правильно разрушен в случае полиморфизма (полиморфизм будет подробно обсуждаться в разделе 2.4). Если вы не добавите ключевое слово override, компилятор выдаст предупреждение, похожее на «Метод 'Destroy' скрывает виртуальный метод базового типа 'TObject'». Предупреждение означает, что определенный вами Destroy скрывает виртуальный метод TObject.Destroy() базового класса. В этом случае объект не может быть правильно уничтожен в полиморфных ситуациях.
Примечание. Деструкторы необходимо объявлять с помощью оператора переопределения.
Аналогично, если в вашем классе нет специальных ресурсов, которые необходимо освободить, вам не нужно определять деструктор. Однако при разрушении объекта следует вызывать метод Free() объекта вместо прямого вызова Destroy().
МойСемейныйОбъект.Свободно();
Это связано с тем, что метод Free() определит, является ли сам объект нулевым, а если он не равен нулю, для повышения безопасности будет вызван метод Destroy() объекта. Теперь, когда есть более безопасные способы сделать это, определенно нет причин не делать этого.
Примечание. Никогда не вызывайте Destroy() непосредственно для объекта, а вместо этого вызывайте Free().
Из этого можно сделать вывод, что в Object Pascal вам нужно уделять внимание только выделению и освобождению запрашиваемых объектом ресурсов, и не нужно заботиться о пространстве, занимаемом самим объектом!