Channels ▼

Andrew Koenig

Dr. Dobb's Bloggers

C++ Primer 5th Edition, Part 4: What Makes a Good Example?

August 08, 2012

Last week, I said that one of Barbara's challenges in rewriting the C++ Primer was to find useful programming examples to illustrate language features that C++11 had made easier to use. I think copy constructors are a particularly interesting case.

A useful example of a language feature should give the reader an idea of how — and why — one might use that feature in practice. It doesn't have to be complete, but it does have to be detailed enough to let readers understand how they might complete it. In the case of a copy constructor, there are some additional requirements:

  • The example must do what a copy constructor does, namely create a copy of an object.
  • It must do something other than just copy the object's data members, because that's what happens by default.
  • It must do something other than copying a pointer and incrementing a reference count, because that's what shared_ptr does.

The first of these requirements tends to conflict with the others. The reason is that the whole notion of a copy is that the copy can be used interchangeably with the original. How can one object be equivalent to another and yet not have their data members be copies of each other?

One plausible answer to this question is to define a data structure that keeps track of all objects of a given type. For example, suppose our class is called Thing. We might use a set of Thing pointers for the purpose:

 
     class Thing {
     private:
           static set<Thing*> allThings;
           // …
     };

Every Thing constructor would add this to the set; the destructor would remove it. This strategy would maintain the invariant that allThings contains the address of every Thing in existence.

This example is useful as far as it goes. However, it has a drawback: Every constructor manipulates the set in the same way, and if we take that manipulation out of the picture, we're left with the default copy constructor. So this example doesn't actually do anything particularly interesting in the copy constructor. However, we can make this example more interesting by generalizing it. This particular generalization actually appeared in the fourth edition of the primer, but it takes on new importance in the fifth edition.

The idea is to imagine a program that deals with email messages. Messages can be stored in mailboxes, which indicate how the user has characterized those messages. A single message can be stored in more than one mailbox, and of course a mailbox can store any number of messages. In such a system, one might copy a message because one intends to edit it. Similarly, one might copy a mailbox because one intends to add messages to or remove them from the mailbox.

This message/mailbox example offers some genuinely interesting design questions to explore. Presumably copying a message should leave the copy in the same mailbox(es) as the original. Similarly, copying a mailbox should probably leave the new mailbox holding the same messages as the original, rather than copying all of the messages in the mailbox. Moreover, the example suggests interesting questions to ask about implementation. For example, if deleting a message removes it from all mailboxes that contain it, how does the destructor go about finding the locations of those mailboxes? Does assigning one message to another change the mailboxes to which the left-hand side belongs? Why or why not? What about swapping two messages?

It may seem silly to devote this much effort to finding the right examples. Why not just explain what a copy constructor does and be done with it? The answer, I think, is that the right examples are crucially important to many people's learning. If the examples are too simple, readers don't learn much from them. If they are too complicated, readers don’t understand them, so the readers don't learn anything at all. The trick is to find examples that are rich enough to avoid triviality, but not so complicated as to preclude understanding.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Dr. Dobb's TV