Essential Tools Module User's Guide : Chapter 6 Collection Classes : Template Overview : Value vs. Reference Semantics in Templates
Value vs. Reference Semantics in Templates
The Essential Tools Module collection class templates can be either value-based or pointer-based. Value-based collections use value semantics, maintaining copies of inserted objects and returning copies of retrieved objects. In contrast, pointer-based collections use reference semantics, dealing with pointers to objects as opposed to the objects themselves. See “Storage Methods of Collection Classes” for other examples of value and reference semantics.
Templates offer you a choice between value and reference semantics. In fact, in most cases, you must choose between a value-based or a pointer-based class; for example, either RWTValOrderedVector<T,A>, or RWTPtrOrderedVector<T,A>.
Your choice depends on the requirements of your application. Pointer-based templates are a good choice for maximizing efficiency for large objects, or if you need to have the same group of objects referred to in several ways, requiring that each collection class point to the target objects, rather than wholly contain them.
An Important Distinction
There is a big difference between a value-based collection of pointers, and a pointer-based collection class. You can save yourself difficulty by understanding the distinction.
For example, declaring:
 
// value-based list of RWCString pointers
RWTValDlist< RWCString* > words;
gives you a value-based list, where the values are of type pointer to RWCString. The collection class will concern itself only with the pointers, never worrying about the actual RWCString objects they refer to. Now consider:
 
RWCString* ptr1 = new RWCString ("foo");
words.insert (ptr1);
RWCString* ptr2 = new RWCString ("bar");
std::cout << words.occurrencesOf (ptr2); // Prints 0
The above code prints 0 because the memory locations of the two string objects are different, and the collection class is comparing only the values of the pointers themselves (their addresses) when determining the number of occurrences.
Contrast that with the following:
 
// pointer-based list of RWCStrings
RWTPtrDlist<RWCString> words;
RWCString* ptr1 = new RWCString ("foo");
words.insert (ptr1);
 
// Different object, same string
RWCString* ptr2 = new RWCString ("foo");
std::cout << words.occurrencesOf (ptr2); // Prints 1
Here the collection class is parameterized by RWCString, not RWCString*, showing that only RWCString objects, not pointers, are of interest to the list. But because it is a pointer-based collection class, communicating objects of interest is done via pointers to those objects. The collection class knows it must dereference these pointers, as well as those stored in the collection class, before comparing for equality.