On 23 Jun 2008, at 11:21, Joost van der Sluis wrote:
Op zaterdag 21-06-2008 om 19:23 uur [tijdzone -0700], schreef David
Emerson:
1. If the setlength function is creating an array of things which
happen
to be stored as pointers (ansistrings in str_arr or class instances
in
cls_arr) then will the pointers be initialized to nil by setlength?
Or
do I need to manually initialize all pointers to nil, after calling
setlength? (I guess for ansistrings that would require using
fillchar ... but maybe setlength is already doing this?)
After calling setlength, the items in the array are not initialised.
That's incorrect, the array is set to 0. Also, note: this discussion
is about dynamic arrays, not about open arrays. These are two
completely different beasts.
Note that in the pascal language allocated memory is never
initialised/set to 0. The only exceptions are the variables in
classes.
(There are some functions that allocate memory and initialise is
afterwards explicitely, see the documentation)
And except in cases when you work with reference counted types (such
as ansistrings and the dynamic arrays themselves (i.e., the pointers
to the dynamic arrays)). And contents of dynamic arrays (regardless of
the element type) are also an exception.
Initialising the strings you can do by setting them to an empty
string.
(:= '')
Ansistrings never need to be explicitly initialised to '', that's
their default value.
2. Of course the primary concern is cleaning up. For the ansistring
case, can I simply call:
setlength (str_arr, 0);
...and expect that the ansistring references will be properly
decremented and cleaned up?
You can expect this, but I woudn't know.
It does clean up everything (and this is guaranteed).
3. Similarly for the cls_arr, do I need to explicitly call the
destructor?
for i := 0 to high(cls_arr) do
if cls_arr[i] <> nil then cls_arr[i].Destroy;
setlength(cls_arr, 0);
Yup, it's pretty consistent.
You have to call Free, not Destroy. And in this case you indeed do
have to free the instances, because classes are not reference counted
(unlike ansistrings) and hence not freed automatically (since you may
still have pointers to these references elsewhere).
And of course the "array in array" example comes to mind:
var
str_arr_arr : array of str_arr;
begin
setlength (str_arr_arr, 5);
setlength (str_arr_arr[3], 17);
{...}
// is it necessary to free all of the members as seen below?
Yes
for i := 0 to high(str_arr_arr) do setlength (str_arr_arr[i], 0);
// or will setlength silently do the job anyway?
No
Yes, it will. The reason is that dynamic arrays are reference counted
and hence properly finalized to the full extent that is necessary.
destructor T_my_other_class.Destroy;
begin
for i := 0 to high(str_arr) do str_arr[i] := ''; // again :)
setlength (str_arr, 0);
setlength (int_arr, 0);
// and what about cls_arr, even more messy of course :)
inherited Destroy;
end;
4. Is the above destructor actually doing anything that doesn't
happen
automatically?
The setlengths to 0 aren't needed.
Setting the ansistrings to '' isn't either, so it indeed does not do
anything that doesn't happen automatically.
And the last case, objects embedded in objects:
type
T_my_third_class = class (TComponent)
embedded_cls : T_my_other_class;
bool_arr : bool_array_type;
{...}
end;
5. Do I need to override the destructor with one that explicitly
calls
embedded_cls.Destroy?
Not if you do not have a create that creates embedded_cls. But
normally:
yes.
Correct, except that you have to call .Free rather than .Destroy.
Jonas
_______________________________________________
fpc-pascal maillist - fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal