Destructors
A destructor runs when an object goes away. It is where an object gives back what it holds: memory, a file, a lock. Because the compiler calls it for you, the clean-up cannot be forgotten on any path out of a scope.
type Tracer
declare constructor( byref label as ustring )
declare destructor( )
label as ustring
end type
constructor Tracer( byref label as ustring )
this.label = label
print " + "; label
end constructor
'' The destructor runs when the object goes away.
destructor Tracer( )
print " - "; label
end destructor
sub Work( )
dim as Tracer t = Tracer( "local to Work" )
print " working"
end sub '' t is destroyed here
print "start"
dim as Tracer whole = Tracer( "program-wide" )
print "a scope:"
scope
dim as Tracer first = Tracer( "first" )
dim as Tracer second = Tracer( "second" )
end scope '' last created, first destroyed
print "a procedure:"
Work( )
print "a loop:"
for i as int32 = 1 to 2
dim as Tracer lap = Tracer( "pass " & i )
next '' once per pass
print "a temporary:"
var size = len( Tracer( "temporary" ).label )
print " its label had"; size; " characters"
print "end"
Output
start
+ program-wide
a scope:
+ first
+ second
- second
- first
a procedure:
+ local to Work
working
- local to Work
a loop:
+ pass 1
- pass 1
+ pass 2
- pass 2
a temporary:
+ temporary
- temporary
its label had 9 characters
end
- program-wide
An object is destroyed when the block that declared it ends:
| Declared in | Destroyed |
|---|---|
a scope or other block | at its end |
| a procedure | when the procedure returns |
| a loop body | at the end of every pass |
| an expression, as a temporary | when the statement finishes |
| the program's top level | when the program ends |
Objects in one block are destroyed in reverse order of creation: second
before first. Something created later may depend on something created
earlier, never the other way round, so this order is always safe.
A type has one destructor, with no parameters. If you do not write one, the
compiler still destroys every field: a field that is itself an object gets
its destructor, and a ustring field frees its text, without your help.
Objects made with new live until you delete them; they are covered in
Memory and Resources. When a type is meant to be
destroyed through a pointer to its base type, its destructor must be
virtual: see Virtual destructors.
Activities
- Add a third
Tracerto the scope and predict the order of the lines. - Put
exit forin the loop on the first pass. Doeslapstill get its destructor?