- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
Containers
A container is a data structure that manages a collection of elements. The container itself is responsible for the allocation and deallocation of its elements, as well as methods for adding and deleting elements. Containers most typically contain constructors and destructors as well.
The containers supplied in the STL consist of two categories: sequence and associative. Sequence containers store elements in sequential order, like a C++ array (which is, in fact, a container). Sequence containers are List, Deque, and Vector. Associative containers are not sequential and use keys to access data. The keys usually are strings or numeric. The associative containers consist of Map, Multimap, Multiset, and Set.
Sequence Containers
Sequence containers store elements in sequential order. It is a linear arrangement where every element in the container is related to the other elements by its position. The containers Vector, List, and Deque are sequence containers.
The Vector Container
The Vector container takes care of the shortcomings of the C++ array. Unlike the C++ array, the vector is an expandable array: It doesn't have to specify its size at compile time. It is very fast and efficient at inserting and removing elements at the end of the array and is quick at random access, but it is slow at inserting or deleting elements from the middle. Table 13.1 lists the member functions and type definitions of the Vector container.
Table 13.1. The Vector Container: Member Functions and Type Definitions
| Function | Definition |
| allocator_type | Type definition for template. |
| assign | Assignment function for sequences. |
| at | Returns a reference to the element of the controlled sequence. |
| back | Returns a reference to the last element of the controlled sequence. The last element must be non-empty. |
| begin | Returns a random-access iterator that points to the first element of the sequence. |
| capacity | Returns a value equal to the storage currently allocated to hold the controlled sequence. This value will be at least as large as size(). |
| clear | Calls erase(), begin(), and end(). |
| const_iterator | Type definition for constant random-access iterator for the sequence. |
| const_reference | Type definition for a constant reference to an element for the sequence. |
| const_reverse_iterator | Type definition for a constant reverse iterator for the sequence. |
| difference_type | Signed integer type defines an object that can represent the difference between the addresses of any two elements of the sequence. |
| empty | Returns True for an empty sequence. |
| end | Returns a random-access iterator that points just beyond the end of the sequence. |
| erase | Function that can remove the element of the sequence pointed to by it or remove a range of elements. |
| front | Returns the first element of a sequence. The first element must be non-empty. |
| get_allocator | Returns allocator. |
| insert | Inserts an element, a repetition of elements, or the sequence. When inserting a single element, the iterator of the element is returned. |
| iterator | Type definition that can serve as a random-access iterator for the sequence. |
| max_size | Returns the length of the largest sequence the object can use. |
| operator[] | Returns a reference to the element of the sequence at the declared position. |
| pop_back | Removes the last element of the sequence. The last value must be empty. |
| push_back | Inserts an element at the end of the sequence. |
| rbegin | Returns a reverse iterator that points just beyond the end of the sequence. |
| reference | Type definition for an object that can be a reference to an element of the sequence. |
| rend | Returns a reverse iterator that points to the first element of the sequence. |
| reserve | Ensures the storage currently allocated to hold the controlled sequence. The size of the storage is returned. |
| resize | Ensures the storage currently allocated to hold the controlled sequence. If the size of the sequence must be increased, it adds the number of elements specified. |
| reverse_iterator | Type definition that can serve as a reverse iterator for the sequence. |
| size | Returns the length of the sequence. |
| size_type | Type definition that describes an object that can represent the length of a sequence. |
| swap | Swaps two sequences. |
| value_type | Type definition for value_type. |
| vector | Constructor for the vector template class. It can specify an empty sequence, a repetition of elements, or a copy of another sequence. |
A code example of the common Vector functions follows. The functions represented in this code are back, empty, erase, pop_back, push_back, Operator[], size, and swap.
Example 13.1. Common Vector Operations
//Common Vector Operations
//
// Member Functions: push_back, pop_back, size, Operator[]
// swap, empty, back, insert, erase
#include <iostream>
#include <vector>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR VectorSet1; //Declare 4 vectors of integer
INTVECTOR VectorSet2(3) ;
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
//Insert Elements using push_back
VectorSet1.push_back(1);
VectorSet1.push_back(2);
VectorSet1.push_back(3);
//Insert Elements using Operator[]
VectorSet2[0] = 10;
VectorSet2[1] = 11;
VectorSet2[2] = 12;
//Print Vector Size
cout << "The Size of VectorSet1 is: " << VectorSet1.size() << endl << endl;
// print VectorsSet1 contents
cout << "Contents of VectorSet1:" << endl;
for(MyIterator = VectorSet1.begin();
MyIterator != VectorSet1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
// print VectorsSet2 contents
cout << "Contents of VectorSet2:" << endl;
for(MyIterator = VectorSet2.begin();
MyIterator != VectorSet2.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//Swap VectorSet1 with VectorSet2
VectorSet1.swap(VectorSet2);
// print VectorsSet1 contents
cout << "Contents of VectorSet1 after Swap:" << endl;
for(MyIterator = VectorSet1.begin();
MyIterator != VectorSet1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
// print last element in VectorSet1
cout << "Last element in VectorSet1: " << VectorSet1.back() << endl;
//Empty out vector1
while( !VectorSet1.empty() )
{
cout << "Popping element " << VectorSet1.back() << endl;
VectorSet1.pop_back();
}
cout << endl;
cout << "Contents of VectorSet1:" << endl;
for(MyIterator = VectorSet1.begin();
MyIterator != VectorSet1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//Insert number 44
VectorSet2.insert(VectorSet2.begin() + 1, 44);
// print VectorsSet2 contents after insert
cout << "Contents of VectorSet2 after insert:" << endl;
for(MyIterator = VectorSet2.begin();
MyIterator != VectorSet2.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//Erase number 44
VectorSet2.erase(VectorSet2.begin() + 1);
// print VectorsSet2 contents after erase
cout << "Contents of VectorSet2 after erase:" << endl;
for(MyIterator = VectorSet2.begin();
MyIterator != VectorSet2.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
} //END
The output of this code follows:
The Size of VectorSet1 is: 3 Contents of VectorSet1: 1 2 3 Contents of VectorSet2: 10 11 12 Contents of VectorSet1 after Swap: 10 11 12 Last element in VectorSet1: 12 Popping element 12 Popping element 11 Popping element 10 Contents of VectorSet1: Contents of VectorSet2 after insert: 1 44 2 3 Contents of VectorSet2 after erase: 1 2 3
The List Container
The List container allows the quick addition and removal of elements anywhere in the list. This is kind of like the linked-list version of the Vector container. Though quick to access either end, it is slow at random access. Table 13.2 lists the member functions and type definitions of the List container.
Table 13.2. The List Container: Member Functions and Type Definitions
| Function | Description |
| allocator_type | Type definition for template. |
| assign | Assignment function for sequences. |
| at | Returns a reference to the element of the controlled sequence. |
| back | Returns a reference to the last element of the controlled sequence. The last element must be non-empty. |
| begin | Returns a random-access iterator that points to the first element of the sequence. |
| clear | Calls erase(), begin(), and end(). |
| const_iterator | Type definition for constant random-access iterator for the sequence. |
| const_reference | Type definition for a constant reference to an element for the sequence. |
| const_reverse_iterator | Type definition for a constant reverse iterator for the sequence. |
| difference_type | Signed integer type defines an object that can represent the difference between the addresses of any two elements of the sequence. |
| empty | Returns True for an empty sequence. |
| end | Returns a random-access iterator that points just beyond the end of the sequence. |
| erase | Function that can remove the element of the sequence pointed to by it or remove a range of elements. |
| front | Returns the first element of a sequence. The first element must be non-empty. |
| get_allocator | Returns allocator. |
| insert | Inserts an element, a repetition of elements, or the sequence. When inserting a single element, the iterator of the element is returned. |
| iterator | Type definition that can serve as a random-access iterator for the sequence. |
| list | Constructor for the list template class. It can specify an empty sequence, a repetition of elements, or a copy of another sequence. |
| max_size | Returns the length of the largest sequence that the object can use. |
| merge | Merges two sequences. |
| operator[] | Returns a reference to the element of the sequence at the declared position. |
| pop_back | Removes the last element of the sequence. The last value must be empty. |
| pop_front | Removes the first element of the sequence. The first value must be non-empty. |
| push_back | Inserts an element at the end of the sequence. |
| push_front | Removes an element from the front of the sequence. |
| rbegin | Returns a reverse iterator that points just beyond the end of the sequence. |
| reference | Type definition for an object that can be a reference to an element of the sequence. |
| remove | Removes elements from the sequence. |
| remove_if | Removes elements from the sequence based on a condition. |
| rend | Returns a reverse iterator that points to the first element of the sequence. |
| resize | Ensures the storage currently allocated to hold the controlled sequence. If the size of the sequence must be increased, it adds the number of elements specified. |
| reverse | Reverses the order of the elements in a sequence. |
| reverse_iterator | Type definition that can serve as a reverse iterator for the sequence. |
| size | Returns the length of the sequence. |
| size_type | Type definition that describes an object that can represent the length of a sequence. |
| sort | Orders the elements of the sequence by a determined predicate. |
| splice | Performs splice operations on the elements in the sequence. |
| swap | Swaps two sequences. |
| value_type | Type definition for value_type. |
| unique | Removes duplicate elements that equal the desired value. |
The following example demonstrates three functions that are unique to List: merge(), reverse(), and unique().
Example 13.2. Common Vector Operations 2
//Common Vector Operations
//
// Member Functions: merge, reverse, and unique
#include <iostream>
#include <list>
#include <string>
using namespace std ;
typedef list<string> LISTSTR;
//Main
void main(){
LISTSTR List1;
LISTSTR List2;
LISTSTR::iterator MyIterator;
List1.push_back("1");
List1.push_back("2");
List1.push_back("3");
List2.push_back("3");
List2.push_back("4");
List2.push_back("5");
// print VectorsSet1 contents
cout << "Contents of List1:" << endl;
for(MyIterator = List1.begin();
MyIterator != List1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//Merge Both lists
List1.merge(List2);
// print VectorsSet1 contents
cout << "Contents of List1 after merge:" << endl;
for(MyIterator = List1.begin();
MyIterator != List1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//Reverse List1
List1.reverse();
// print VectorsSet1 contents
cout << "Contents of List1 after reverse:" << endl;
for(MyIterator = List1.begin();
MyIterator != List1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
//remove duplicates List1
List1.unique();
// print VectorsSet1 contents
cout << "Contents of List1 after unique:" << endl;
for(MyIterator = List1.begin();
MyIterator != List1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
} //END
Unless you specify -GX when compiling, you will receive numerous warnings upon compiling the program. The results of this program are pretty obvious, as shown here:
Contents of List1: 1 2 3 Contents of List1 after merge: 1 2 3 3 4 5 Contents of List after reverse: 5 4 3 3 2 1 Contents of List1 after unique: 5 4 3 2 1
The Deque Container
The third sequence container is the Deque (double-ended queue). The Deque is actually like a stack and queue combined. Like a stack, all the input and output takes place at the top of the stack (LIFO). In a queue, all data goes in the front and comes out the back (FIFO). With the Deque container, these attributes are combined so that elements can be inserted or deleted at either end. This makes it quite flexible and thus is used as the basis for stacks and queues. Table 13.3 lists the member functions and type definitions of the Deque container.
Table 13.3. The Deque Container: Member Functions and Type Definitions
| Function | Description |
| allocator_type | Type definition for template. |
| assign | Assignment function for sequences. |
| at | Returns a reference to the element of the controlled sequence. |
| back | Returns a reference to the last element of the controlled sequence. The last element must be non-empty. |
| begin | Returns a random-access iterator that points to the first element of the sequence. |
| clear | Calls erase(), begin(), and end(). |
| const_iterator | Type definition for constant random-access iterator for the sequence. |
| const_reference | Type definition for a constant reference to an element for the sequence. |
| const_reverse_iterator | Type definition for a constant reverse iterator for the sequence. |
| difference_type | Signed integer type defines an object that can represent the difference between the addresses of any two elements of the sequence. |
| empty | Returns True for an empty sequence. |
| end | Returns a random-access iterator that points just beyond the end of the sequence. |
| erase | Function that can remove the element of the sequence pointed to by it or remove a range of elements. |
| front | Returns the first element of a sequence. The first element must be non-empty. |
| get_allocator | Returns allocator. |
| insert | Inserts an element, a repetition of elements, or the sequence. When inserting a single element, the iterator of the element is returned. |
| iterator | Type definition that can serve as a random-access iterator for the sequence. |
| list | Constructor for the list template class. It can specify an empty sequence, a repetition of elements, or a copy of another sequence. |
| max_size | Returns the length of the largest sequence the object can use. |
| merge | Merges two sequences. |
| operator[] | Used to reference elements directly. |
| pop_back | Removes the last element of the sequence. The last value must be empty. |
| pop_front | Removes the first element of the sequence. The first value must be non-empty. |
| push_back | Inserts an element at the end of the sequence. |
| push_front | Inserts an element at the beginning of the sequence. |
| rbegin | Returns a reverse iterator that points just beyond the end of the sequence. |
| reference | Type definition for an object that can be a reference to an element of the sequence. |
| rend | Returns a reverse iterator that points to the first element of the sequence. |
| resize | Ensures the storage currently allocated to hold the controlled sequence. If the size of the sequence must be increased, it adds the number of elements specified. |
| reverse | Reverses the order of the elements in a sequence. |
| reverse_iterator | Type definition that can serve as a reverse iterator for the sequence. |
| size | Returns the length of the sequence. |
| size_type | Type definition that describes an object that can represent the length of a sequence. |
| swap | Swaps two sequences. |
| value_type | Type definition for value_type. |
An example of a Deque container, supporting push_front, pop_front, and front(), follows:
Example 13.3. Deque Example
//Deque example
//
// Member Functions: push_back, push_front
//
#include <iostream>
#include <deque>
using namespace std ;
typedef deque<int> INTDEQUE;
//Main
void main(){
INTDEQUE::iterator MyIterator;
INTDEQUE deque1;
deque1.push_back(2);
deque1.push_front(1);
deque1.push_back(3);
// print deque contents
cout << "Contents of deque1:" << endl;
for(MyIterator = deque1.begin();
MyIterator != deque1.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl;
} //END
Unless you specify -GX when compiling, you will receive numerous warnings upon compiling the program. The results of this program are pretty obvious, as shown here:
Contents of deque1: 1 2 3
Note the manner of how the elements were placed in the Deque and the final results.
Associative Containers
Associative containers use keys to access data and are not sequential. The keys typically are numeric or strings. The keys are used automatically by the container to arrange the stored elements in a specific order.
There are two types of associative containers in the STL: sets and maps. A set only stores the key without the associated values. A map associates a key with a value. This value can be any type of object.
Both types of containers only allow one key per given value. It is a one-to-one relationship. However, if the need arises for multiple keys per value, the Multiset and Multimap containers are the ones to use.
Table 13.4 lists the member functions and type definitions of Map, Multimap, Set, and Multiset containers. All apply except for the respective constructors and those otherwise noted.
Table 13.4. Map, Multimap, Set, and Multiset Containers: Member Functions and Type Definitions
| Function | Description |
| allocator_type | Type definition for template. |
| begin | Returns a bidirectional iterator that points to the first element of the sequence. |
| clear | Calls erase(), begin(), and end(). |
| const_iterator | Type definition for a constant bidirectional iterator for the sequence. |
| const_reference | Type definition for a constant reference to an element for the sequence. |
| const_reverse_iterator | Type definition for a constant reverse bidirectional iterator for the sequence. |
| count | Returns the number of elements of a given range. |
| difference_type | Signed integer type defines an object that can represent the difference between the addresses of any two elements of the sequence. |
| empty | Returns True for an empty sequence. |
| end | Returns a bidirectional iterator that points just beyond the end of the sequence. |
| equal range | Returns a pair of iterators such that the first one is equal to a given lower bound, and the second is equal to a given upper bound. |
| erase | Function that can remove the element of the sequence pointed to by it or remove a range of elements. |
| find | Returns an interator to the first element it finds matching a given value. If no match is found, the iterator is equal to end(). |
| get_allocator | Returns allocator. |
| insert | Inserts an element, a repetition of elements, or the sequence. When inserting a single element, the iterator of the element is returned. |
| iterator | Type definition that can serve as a bidirectional iterator for the sequence. |
| key_comp | Determines the order of elements in a sequence. |
| key_compare | Compares two sort keys to determine the relative order of any two elements in the sequence. |
| key_type | Type definition for the sort key object in each element of the sequence. |
| lower_bound | Returns an iterator that designates the lower bound of a given element value. If no element is found, end() is returned. |
| map | Constructor for the Map object. |
| max_size | Returns the length of the largest sequence the object can use. |
| multimap | Constructor for the Multimap object. |
| multiset | Constructor for Multiset. |
| operator[] | Returns a reference to the element of the sequence at the declared position. Applies to Map object only. |
| rbegin | Returns a reverse bidirectional iterator that points just beyond the end of the sequence. |
| reference | Type definition for an object that can be a reference to an element of the sequence. |
| referent type | Type definition of referent. |
| rend | Returns a reverse bidirectional iterator that points to the first element of the sequence. |
| reverse_iterator | Type definition that can serve as a reverse iterator for the sequence. |
| set | Constructor for Set. |
| size | Returns the length of the sequence. |
| size_type | Type definition that describes an object that can represent the length of a sequence. |
| swap | Swaps two sequences. |
| upper_bound | Returns an iterator that designates the upper bound of a given element value. If no element is found, end() is returned. |
| value_comp | Returns the order of elements in a sequence. |
| value_compare | Compares the sort keys of two elements to determine their relative order in the sequence. |
| value_type | Type definition for value_type. |
A program example that puts some of this knowledge to work follows. It is quite simple and self-explanatory, but it demonstrates the basics of working with the Vector container class.
Example 13.4. Vector Program Example
// Vector program example
//
// Functions:
// vector::push_back
// vector::pop_back
// vector::begin
// vector::end
// vector::iterator
#include <iostream>
#include <vector>
using namespace std ;
typedef vector<int> INTVECTOR;
void main(){
INTVECTOR MyVector;
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
// MyVector will contain [ 1, 2, 3 ]
MyVector.push_back(1) ;
MyVector.push_back(2) ;
MyVector.push_back(3) ;
// Erase element 3 in vector.
MyVector.pop_back();
// MyVector will contain [ 1, 2 ] at this point
MyVector.push_back(4) ;
// MyVector now contains [ 1, 2, 4 ]
// Print contents of MyVector. Shows [1, 2, 4]
cout << "Results = " ;
for (MyIterator = MyVector.begin();
MyIterator != MyVector.end();
MyIterator++)
{
cout << *MyIterator;
if (MyIterator != MyVector.end()-1) cout << ", ";
}
cout << endl ;
}
Results = 1, 2, 4
Iterators | Next Section

Account Sign In
View your cart