Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Mail Systems
Eclipse Documentation

How To Guides
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Problem Solutions
Privacy Policy




Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Basic sequence operations

Using a template, the following example shows the operations supported by all the basic sequences: vector, deque, and list:

//: C07:BasicSequenceOperations.cpp
// The operations available for all the
// basic sequence Containers.
#include <deque>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
template<typename Container>
void print(Container& c, char* title = "") {
cout << title << ':' << endl;
if(c.empty()) {
cout << "(empty)" << endl;
typename Container::iterator it;
for(it = c.begin(); it != c.end(); it++)
cout << *it << " ";
cout << endl;
cout << "size() " << c.size()
<< " max_size() " << c.max_size()
<< " front() " << c.front()
<< " back() " << c.back()
<< endl;
template<typename ContainerOfInt> void basicOps(char* s) {
cout << "------- " << s << " -------" << endl;
typedef ContainerOfInt Ci;
Ci c;
print(c, "c after default constructor");
Ci c2(10, 1); // 10 elements, values all 1
print(c2, "c2 after constructor(10,1)");
int ia[] = { 1, 3, 5, 7, 9 };
const int IASZ = sizeof(ia)/sizeof(*ia);
// Initialize with begin & end iterators:
Ci c3(ia, ia + IASZ);
print(c3, "c3 after constructor(iter,iter)");
Ci c4(c2); // Copy-constructor
print(c4, "c4 after copy-constructor(c2)");
c = c2; // Assignment operator
print(c, "c after operator=c2");
c.assign(10, 2); // 10 elements, values all 2
print(c, "c after assign(10, 2)");
// Assign with begin & end iterators:
c.assign(ia, ia + IASZ);
print(c, "c after assign(iter, iter)");
cout << "c using reverse iterators:" << endl;
typename Ci::reverse_iterator rit = c.rbegin();
while(rit != c.rend())
cout << *rit++ << " ";
cout << endl;
print(c, "c after resize(4)");
print(c, "c after push_back(47)");
print(c, "c after pop_back()");
typename Ci::iterator it = c.begin();
++it; ++it;
c.insert(it, 74);
print(c, "c after insert(it, 74)");
it = c.begin();
c.insert(it, 3, 96);
print(c, "c after insert(it, 3, 96)");
it = c.begin();
c.insert(it, c3.begin(), c3.end());
print(c, "c after insert("
"it, c3.begin(), c3.end())");
it = c.begin();
print(c, "c after erase(it)");
typename Ci::iterator it2 = it = c.begin();
++it2; ++it2; ++it2; ++it2; ++it2;
c.erase(it, it2);
print(c, "c after erase(it, it2)");
print(c, "c after swap(c2)");
print(c, "c after clear()");
int main() {
basicOps<vector<int> >("vector");
basicOps<deque<int> >("deque");
basicOps<list<int> >("list");
} ///:~

The first function template, print( ), demonstrates the basic information you can get from any sequence container: whether it s empty, its current size, the size of the largest possible container, the element at the beginning, and the element at the end. You can also see that every container has begin( ) and end( ) member functions that return iterators.

The basicOps( ) function tests everything else (and in turn calls print( )), including a variety of constructors: default, copy-constructor, quantity and initial value, and beginning and ending iterators. There are an assignment operator= and two kinds of assign( ) member functions. One takes a quantity and an initial value, and the other takes a beginning and ending iterator.

All the basic sequence containers are reversible containers, as shown by the use of the rbegin( ) and rend( ) member functions. A sequence container can be resized, and the entire contents of the container can be removed with clear( ). When you call resize( ) to expand a sequence, the new elements use the default constructor of the type of element in the sequence, or if they are built-in types, they are zero-initialized.

Using an iterator to indicate where you want to start inserting into any sequence container, you can insert( ) a single element, a number of elements that all have the same value, and a group of elements from another container using the beginning and ending iterators of that group.

To erase( ) a single element from the middle, use an iterator; to erase( ) a range of elements, use a pair of iterators. Notice that since a list supports only bidirectional iterators, all the iterator motion must be performed with increments and decrements. (If the containers were limited to vector and deque, which produce random-access iterators, operator+ and operator- could have been used to move the iterators in bigger jumps.)

Although both list and deque support push_front( ) and pop_front( ), vector does not, but push_back( ) and pop_back( ) work with all three.

The naming of the member function swap( ) is a little confusing, since there s also a nonmember swap( ) algorithm that interchanges the values of any two objects of same type. The member swap( ) swaps everything in one container for another (if the containers hold the same type), effectively swapping the containers themselves. It does this efficiently by swapping the contents of each container, which consists mostly of pointers. The nonmember swap( ) algorithm normally uses assignment to interchange its arguments (an expensive operation for an entire container), but it is customized through template specialization to call the member swap( ) for the standard containers. There is also an iter_swap algorithm that uses iterators to interchange two elements in the same container.

The following sections discuss the particulars of each type of sequence container.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire