Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the Delphi design principles behind class instances and pointers?

Coming from a C++ background, I understand classes, pointers and memory addresses reasonably well. However, with Delphi, I am finding myself confused.

I understand that when you declare a variable of a particular type of class in the var section of a function/procedure, what you're really declaring is a POINTER to that class. E.g., the following Delphi and C++ are roughly equivalent, both allocating the amount of memory required 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 the use of virtual methods for class hierarchies. However, if you don't have class hierarchies, you can declare a variable on the stack (which executes faster). If you need to pass the variable around as a pointer, you can simply get its address with 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 stage, I have a few questions regarding Delphi's use of classes and pointers.

  1. If creating an object with o := MyObject.Create uses heap-allocation in Delphi, how do you allocate an object on the stack?
  2. If a variable of a specific type of class declared as o: MyObject is really a pointer, then why is the ^ pointer symbol never used. Is this a "convenience" idiom in Delphi?
  3. How can you get the address of the actual MyObject located on the heap? I have 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.
    

It's possible that I have misunderstood some Delphi fundamentals, but I have not found anyone (physically or on the Internet) who can explain the above to my satisfaction.

EDIT

Given that Delphi typically only allocates memory on the heap, then:

  1. Does assigning one object to another mean that they both point to the same address?
  2. Why does the assignment ("THIS ASSIGNMENT") not compile?

    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's 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 multiple variables that should be pointing to the same object but may be pointing to different objects, so I want to compare their memory location to determine if this is the case.)

like image 726
magnus Avatar asked Feb 23 '14 23:02

magnus


People also ask

What are classes and objects in Delphi?

A class, or class type, defines a structure consisting of fields, methods, and properties. Instances of a class type are called objects. The fields, methods, and properties of a class are called its components or members. A field is essentially a variable that is part of an object.

How do you define a class in Delphi?

To define a class: In the IDE, start with a project open and choose File > New > Unit to create a new unit where you can define the new class. Add the uses clause and type section to the interface section. In the type section, write the class declaration.


1 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 are always allocated on the heap.

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

Yes.

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

Try this:

WriteLogLine('Address of object: ' + Format('%p', [Pointer(o)]));
like image 192
Remy Lebeau Avatar answered Oct 03 '22 21:10

Remy Lebeau