What About References?
As a detective, I know a thing or two about aliases.
Wonderful! You should be able to help us out, then!
Allocation Phase
In our model, no extra space is allocated for the reference, since it's another name for an existing object (whose space has already been allocated).
(Of course we know that references often do require some space to be allocated in practice, but our model abstracts this implementation detail away.)
That seems logical. No matter how many aliases I take on, I'm still just one Sherlock.
Initialization Phase
Nothing happens to the value, regardless of whether it's a reference to a primitive or an instance of a class. The only thing that happens is that the reference name becomes useable.
Again, this matches my detective experience. When I take on a new alias, I do not change who, or what, I am. I merely begin to respond to a new name.
That's… surprisingly deep.
Use Phase
Any attempts to use the reference are the same as attempts to use the thing it refers to.
I pride myself in my ability to respond naturally to all of my aliases!
Destruction Phase
Nothing happens to the value, regardless of whether it's a reference to a primitive or an instance of a class. The only thing that happens is that the name becomes unusable.
It would indeed be a tragedy if shaking off an alias caused any long-term change to my being.
Deallocation Phase
In our model, no space is deallocated for the reference, since it's another name for an existing object.
(In practice, there may be some behind-the-scenes inner-workings memory associated with the reference that is deallocated along with the rest of the stack frame, but we don't need to worry about that.)
The space for the object will be deallocated, when its time comes, according to the object-lifetime rules of the object itself, which doesn't necessarily happen at the same time as the reference's destruction/deallocation!
Aliases come and go, but I remain. Still, I am acutely aware that deallocation comes to us all eventually.
That… went a little dark.
Anyway, thank you for the expert insights!
An Easy Way To Remember
Our lifecycle model really reflects what's happening with the boxes in our memory model. We don't draw any boxes for references, so the allocation, initialization, destruction, and deallocation phases don't do anything to the contents of the boxes!
Initialization and destruction just involve writing or crossing out a name.
Practice Problem
Suppose that, once again, we have Cow
functions with print statements in them,
Cow::Cow() {
cout << "Cow default constructor called!" << endl;
}
Cow::Cow(const Cow& other) {
cout << "Cow copy constructor called!" << endl;
}
Cow::operator=(const Cow& other) {
cout << "Cow assignment operator called!" << endl;
}
Cow::~Cow() {
cout << "Cow destructor called!" << endl;
}
and that we write the following program that uses our functions:
1| int main() {
2| Cow bessie{};
3| Cow mabel = bessie;
4| Cow& daisy = mabel;
5| bessie = daisy;
6| }
(When logged in, completion status appears here.)