Of course, the program using this class kept crashing intermittently with memory corruption, because I'd violated the Law of the Big Three: Whenever you provide any one of a destructor, copy constructor or assignment operator, you will generally need to provide all three. "So," said I to myself, said I, "I have to handle copying and assignment. Simple...
auto_ptr already has a copy constructor and assignment operator, so I'll use that." (You've heard of the
auto_ptr in the original C++ library, right?)
auto_ptr automatically deletes the object it points to, all I had to do was change the type of xItem and remove the delete statement in the destructor --
auto_ptr would take care of the rest, right?
Unfortunately, my program was still crashing, this time because it was trying to dereference a null pointer. I had been trying to puzzle out the problem for about half an hour when the Guru, thin as a rail, decided to walk by, carrying a thick book open in one hand. She did that a lot... show up at propitious times, I mean; I think it was some sort of prescient thing. Downright spooky, actually.
"Uh, what're you reading?" I asked her, pointing at her book to deflect attention away from my screen and hoping she would go away.
The Guru blinked. "The writings of Josuttis," she said softly, marked her page, and closed the book. "What's that you have there, young one?"
"I'm having problems with this wrapper class I'm writing," I admitted. "I'm using an
auto_ptr member, but in my test harness its pointer keeps getting reset to null for some reason."
"Show me your writings," the Guru said. I showed her the screen. "Ownership," she said immediately, after barely a glance.
It was my turn to blink.
"Ownership, child; your problem is ownership semantics. No person can serve two masters, and no pointer can serve two
Her words, although certifiably strange, made me realize my mistake. "Okay, right," I nodded. "When you copy an
auto_ptr, the original one relinquishes ownership and gets reset to null. My
xWrapper copy constructor reuses that default behavior, so the original
auto_ptr is being reset, and when I try to access it I'm dereferencing a null pointer."
"Correct," the Guru agreed. "You have done well to reuse the true tools of the Standard, but you must take care with them. For
xWrapper, you must still manage
xWrapper copying and assignment yourself."
"But I can't implement them in terms of
auto_ptr's own versions because those won't do the ri--- Oh. I get it. I'll use
auto_ptr's dereference operator to access the owned objects." I quickly wrote out the two functions:
"Hey, cool." This, I liked. "I don't even need to check for self-assignment in the assignment operator."
"That is correct."
I should have stopped then and kept my mouth shut, but I wasn't that smart yet. "
auto_ptr sure is easy to misuse. If only it could have told me I was trying to transfer ownership when I didn't expect that to happen..."
"Peace!" interrupted the Guru. "The fault is not with
auto_ptr in this instance. You should have said that you did not want the
auto_ptr to be copied, had that been your desire."
"But how? That's not possible."
"Ah, but it is. Remember the blessings of const-correctness. The way to state that an
auto_ptr is immutable is to make it
const. Had you made the member a
const auto_ptr, the compiler would not have been able to silently perform the copy of the
xWrapper object. Alternatively, had you used something like the
strict_auto_ptr from the Second Revisionist rendering of Cline 30:12, the compiler would not have been able to mistakenly generate incorrect
xWrapper copying and assignment. Of course, in this case making it
const would have been simpler and sufficient."
She reopened her copy of Josuttis and resumed reading as she started to walk away, still talking to me absently, both she and her voice gradually drifting away: "A word of caution, my child...
auto_ptr is a useful tool, but as you have discovered, it is not a panacea. Read and meditate upon Josuttis chapter 4. You must never instantiate a Standard container of
auto_ptr, such as
auto_ptr does not meet the copying and assignment requirements of the Standard. Furthermore, never attempt to use
auto_ptr to point to an array of objects, for the
auto_ptr's destructor uses non-array
delete to delete the object it owns; for an array of objects, use a
vector instead. The library..."
But then she turned a corner, and was gone. It was only my second day; I wondered, not idly, if I ought to update my résumé while I could still pretend this job had never happened.
- - - - -
"Weird lizard," Jeannine opined, sipping coffee as we exited the Terran local traffic control area, still gaining velocity. "So, did you leave?"
"She was, but no. I'm not sure why," I added honestly. "A few run-ins like that, and I was ready to leave during probation like the rest. I guess he grew on me, though. Didn't you ever work with a quirk like that?"
"Mmm. Some. I suppose."
It was not the last time I would speak with Jeannine about the Guru, or about more pleasant things.