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.
- If creating an object with
o := MyObject.Create
uses heap-allocation in Delphi, how do you allocate an object on the stack? - 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? 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:
- Does assigning one object to another mean that they both point to the same address?
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.)
MyObject o();
declares a function, you certainly meanMyObject o;
. – user395760type1 name(type2());
-- Wheretype1
is meant to be the type of a variable, but is actually the return type of a function, name is the name of the function, andtype2()
is meant to be a default constructed object, but is actually a parameter of a function type (which takes no arguments and returns atype2
object). – Benjamin Lindley