What are the principles of Delphi design for class instances and pointers?

Based on the background of C ++, I understand the classes, pointers, and memory addresses well. However, with Delphi, I find myself confused.

I understand that when you declare a variable of a specific type of a class in the var section of a function / procedure, what you actually declare is the POINTER for this class. For example, the following Delphi and C ++ are roughly equivalent, both allocate the amount of memory needed for the MyObject class on the heap.

 // Delphi procedure Blah.Something(); var o: MyObject; begin o := MyObject.Create; o.Free; end; // C++ void Blah::Something() { MyObject *o = new MyObject(); delete o; } 

In C ++, using pointers (and references) allows you to use virtual methods for a class hierarchy. However, if you do not have a class hierarchy, you can declare a variable on the stack (which is faster). If you need to pass the variable around as a pointer, you can simply get its address using the & operator.

 // C++ void Blah::Something() { // This is allocated on the stack. MyObject o; // This address of this stack-allocated object is being used. doSomethingWithAnOhPointer(&o); } 

At this point, I have several questions regarding the use of classes and pointers in Delphi.

  • If you use o := MyObject.Create distribution in Delphi when creating an object with o := MyObject.Create , how do you allocate the object on the stack?
  • If a variable of a particular class type declared as o: MyObject is really a pointer, then why the ^ character of the pointer was never used. Is this a "convenient" idiom in Delphi?
  • How can you get the address of the actual MyObject on the heap? I tried: the following.

     WriteLogLine('Address of object: ' + Format('%p', [@o])); // This prints the address of the 'o' pointer. WriteLogLine('Address of object: ' + Format('%p', [o])); // This causes the program to crash. 

I may have misunderstood some of the basics of Delphi, but I have not found anyone (physically or on the Internet) who can explain this above my satisfaction.

EDIT

Given that Delphi usually allocates memory on the heap, then:

  • Does assigning one object to another mean that both of them point to the same address?
  • Why is the assignment ("THIS RECORDING") not compiled?

     procedure Blah.Something(); var o1: MyObject; o2: MyObject; oP: ^MyObject; begin o1 := MyObject.Create; o2 := o1; // Both variables "o1" and "o2" point to the same object on the heap. WriteLogLine(Format('@o1 = %p, @o2 = %p', [@o1, %o2])); // This SHOULD produce two different address, as it the address of the "implied pointer". oP := o1; // THIS ASSIGNMENT will NOT compile. WriteLogLine(Format('oP = %p', [oP] o1.Free; o1 := nil; // The single object has been deleted, but o1 = nil while o2 <> nil end; 

(To give some context, there are several variables that must point to the same object, but can point to different objects, so I want to compare their location in memory to determine if this is so.)

+6
source share
3 answers

If creating an object with o: = MyObject.Create uses heap allocation in Delphi, how do you allocate an object on the stack?

Delphi does not allow class instances to be allocated on the stack. They always stand out on a bunch.

If a variable of a particular class type declared as o: MyObject is really a pointer, then why the ^ pointer symbol has never been used. Is this a "convenient" idiom in Delphi?

Yes.

How can you get the address of the actual MyObject on the heap?

Try the following:

 WriteLogLine('Address of object: ' + Format('%p', [Pointer(o)])); 
+8
source

I am not very good at delphi, but here it goes.

Unlike Object Pascal , Delphi does not have a stack distribution for objects .. Well, not without using an assembly, that is.

You can actually use the ^ pointer syntax, but you will need to use AllocMem or similar to allocate memory for the pointer:

 Function AllocSomeClass: ^SomeClass; begin Result := AllocMem(SizeOf(SomeClass); //FreeMem. end; 

Of course, if the class has an init function or constructor or creates a function, then just making SomeClass.Create is the best option.

Regarding the use of assembly, you can see these two:

http://www.kbasm.com/delphi-stack-local-object.html

And is there a Delphi memory management function that allocates memory on the stack?

To print addresses:

Format('%p %p %d', [@ptr, ptr, ptr^]);

It displays the address of the ptr variable, the address stored in ptr , and the ptr value (the data it points to), respectively.

Another option is to use records instead of objects to distribute the stack. Entries are always on the stack unless otherwise indicated. Objects need to highlight or call the create function / constructor.

Entries cannot replace objects, but that's all I can think of at the moment.

+3
source

How can you allocate an object on the stack?

You can not.

Why can access to members of an object be absent ^ ? It is just a convenience.

Yes, it is a convenience. In fact, it can also be omitted when using a variable that is a pointer to a record.

How can I get the address of an object?

Use Format('%p', [Pointer(o)]) .

Does assigning one object to another mean they both have the same address?

Do not think o1 := o2 how to assign one object to another. Instead, think of it as assigning one link to another, or assigning one pointer to another. Since the object variable is implemented as a pointer, this assignment simply assigns an address.

Why is oP := o1 not compiling?

Because oP is of type ^MyObject , which is a double pointer. In C ++ terms, this code is akin to trying to assign obj* obj** .

+1
source

All Articles