1.3 Airline Connections
Airline Connections
Lest you think that this issue only arises in
low-level data structures, let’s consider how it might arise
in programming at the application level.
This graph illustrates flight connections
available from an airline.
Aggressively Deleting a Graph
If we were to implement this airport graph with
Big 3-style operations:
class
Airport
{
⋮
private
:
vector
<
Airport
*
>
hasFlightsTo
;
};
Airport
::~
Airport
()
{
for
(
int
i
=
0;
i
<
hasFlightsTo
.
size
();
++
i
)
delete
hasFlightsTo
[
i
];
}
we would quickly run into a disaster.
Deleting the Graph
Suppose that we delete the Boston
airport.
- Its destructor would be invoked, which would
delete the N.Y. airport and Wash DC airports.
- Let’s say, for the sake of example, that
the NY airport is deleted first.
- The act of deleting the pointer to the NY
airport causes its destructor to be invoked, which would delete the
Boston and Wash DC airports.
- But Boston has already been deleted.
- If we don’t crash right away, we will
quickly wind up deleting Wash DC twice.
- In fact, we would wind up, again, in an
infinite recursion among the destructors.
This should not be a big surprise. Looking at the graph, we can see
that it is possible to form cycles. (In fact, if there is any node
in this graph that doesn’t
participate in a cycle, there would be something very wrong with
our airline. Either we would have planes piling up at some airport,
unable to leave; or we would have airports that run out of planes
and can’t support any outgoing flights.
The Airline
Now, you might wonder just how or why we would
have deleted that Boston pointer in the first place. So,
let’s add a bit of context.
∙ The airport graph is
really a part of the description of an airline:
class
AirLine
{
⋮
string
name
;
map
<
string
,
Airport
*
>
hubs
;
};
AirLine
::~
Airline
()
{
for
(
map
<
string
,
Airport
*
>::
iterator
i
=
hubs
.
begin
;
i
!=
hubs
.
end
();
++
i
)
delete
i
-
>
second
;
}
The AirLine Structure
- The map hubs
provides access to all those airports where planes are serviced and
stored when not in flight, indexed by the airport name.
- Not all airports are hubs.
- An airport that is not a hub is simply one
where planes touch down and pick and discharge passengers while on
their way to another hub.
Suppose that PuddleJumper Air goes
bankrupt.
- It makes sense that when an airline object is
destroyed, we would delete those hub pointers.
- But we’ve seen that this is
dangerous.
Can We Do Better?
Now, that’s a problem. But what makes this
example particularly vexing is that it’s not all that obvious
what would constitute a better approach.
- Let’s consider some other changes to the
airline structure.
Changing the Hubs
Suppose that Wash DC were to lose its status as a
hub.
Even though the pointer to it were removed from
the hubs table, the Wash DC airport
needs to remain in the map.
Changing the Connections
On the other hand, if Wash DC were to drop
its service to Norfolk, one might argue that Norfolk and Raleigh
should then be deleted, as there would be no way to reach them.
- But how could you write code into your
destructors and your other code that adds and removes pointers that
could tell the difference between these two cases?