Debugging

•      There are programs to help you find runtime error

•      You program must compile to use a debugger

•      In the lab tomorrow, you will be introduced to GDB, the GNU debugger

–    This is certainly not the best debugger available, but from it you can at least learn what a debugger can do.

–    I urge you to explore other debuggers.

•      Online references for GDB

–    The GDB home page

–    GDB user’s manual

 

The Standard Template Library

SGI Reference

General Overview

•      The STL is a generic library

–    that provides solutions to managing collections of data

–    with modern and efficient algorithms.

•      From a programmers point a view, the STL provides a bunch of collection classes that meet different needs, as well as algorithms that operate on them.

•      Using it means you can forget programming

–    Dynamic arrays

–    Linked lists

–    Binary trees

–    Different search or sort algorithms

•      But all this programming power comes at a price—it is not especially easy to learn to use.

 

STL Components

•       Containers

–    These are data structures designed to hold or contain data

–    Every kind of container has it’s own advantages and disadvantages

–    They may be implemented as arrays, linked lists or trees

•       Iterators

–    These are smart pointers

•    They step through  an array the same way they step through a linked list or a tree

–    The interface is much like pointers

•    Increment using  the ++ operator

•    Dereference use the * operator

–    Every container class provides it own iterator type that knows the internal structure of its container

•       Algorithms          

–    These are global functions used to process the elements of containers.

–    Usually the first two arguments are iterators denoting a range

–    They search, sort, modify, or otherwise use the elements

 

  Example: prints all the elements of a list container

•       /* The following code example is taken from the book  "The C++ Standard Library - A Tutorial and Reference"  (C) Copyright Nicolai M. Josuttis 1999. */
#include <iostream>      
#include <list>
using namespace std;

int main( )
{    list<char> coll;
      // instantiates the list container for character elements  
                                     
     for (char c='a'; c<='z'; ++c)  // append elements from 'a' to 'z'     
     {    coll.push_back(c);  
      }
  
 /* print all elements    * pos iterates over all elements     */   
list<char>::const_iterator pos;     // instantiate the iterator
 for (pos = coll.begin( ); pos != coll.end( );  ++pos)
      {        cout << *pos << ' ';    }   
cout << endl;
}

 

int main()
{    vector<int> coll;    //instantiates a vector of ints

          vector<int>::iterator pos;   // instantiates an iterator for vectors

 // insert elements from 1 to 6 in arbitrary order   

    coll.push_back(2);    coll.push_back(5);   coll.push_back(4);    coll.push_back(1);   coll.push_back(6);    coll.push_back(3);

// find and print minimum and maximum elements

    pos = min_element (coll.begin( ), coll.end( ));

            cout << "min: " << *pos << endl;

    pos = max_element (coll.begin( ), coll.end( ));

             cout << "max: " << *pos << endl;  

 // sort all elements
 sort (coll.begin( ), coll.end( ));

    pos = find (coll.begin( ), coll.end( ), 3);

// reverse the order of the found element with value 3 and all following elements   

     reverse (pos, coll.end( ));   //pos is the beginning iterator

    // print all elements

    for (pos=coll.begin( ); pos!=coll.end( ); ++pos)
{  cout << *pos << ' '; }   

cout << endl;   }

 

Containers

These are class templates that have member functions to manage the elements

Two general kinds of containers

Sequence container

•    These are collections whose
position depends on time and
place of insertion

•    The position is independent of
the element’s value

Associative containers

•    These are sorted collections

•    The actual position of an element depends on its value due to a certain sorting criterion

 

Iterators

•       An iterator represents a certain position in a container

•       All iterators are defined with these fundamental operations

–    Operator ++ step forward to the next element

–    Operators = = and !=  equal and not equal

–    Operator = the assignment operator

–    Operator * dereferences

•       So the interface to iterators is like a pointer interface (i.e. they are used the same)

•       Ordinary pointers may be used in place of iterators if convenient (as arguments for algorithms)

•       An iterators is a class nested inside the collection class template

•       The user must instantiate objects
of the iterator class to use them.

•       There are different types of
interators, depending on the class
through which they iterate

 

Container class member functions

  begin( )

–     Returns an iterator that is the beginning position of the first element of the container

 

  end( )

–     Returns an iterator that is one byte past the end of the elements in the container.

–     This is also call a past-the-end iterator

  

size( )

–     Returns the number of items in the container

 

   empty( )

–     Returns true if the container is empty

 

  push_back ( )

–     Adds an element to the end of a sequential container

 

Algorithms  

•       These are global function templates that operate on containers through iterators

•       They are designed to work with STL containers, but can be applied to ordinary C++ arrays.

•       The first two args are a pair of iterators (first, last) marking off the range of elements in the container over which to operate

–    The elements are usually written [first, last) 

–    It must be possible to reach last beginning with first through repeated application of the increment operator

 

•       Different algorithms require different iterator types

–    The minimum category of iterator is indicated in documentation

–    Example: find( ) requires a one-pass, read-only iterator; iterators that do more (bidirectional, random access) work as well. 

–    Some algorithms have multiple versions with different arguments

–    For those algorithms that modify the container over which they operate, there are generally two versions i.e. replace( ) and replace_copy( )

 

Some simplified STL algorithms

•       iter copy (iter first, iter last, iter result);

–    Copies [first, last), putting copy at result; returns pointer one past the  end of the resulting sequence

–    Note:  it is always an error to dereference last

•       iter find (iter first, iter last, const T &val);

–    Searches [first,last) for val;

–    returns an iterator to the first occurrence of the element or to end if the value is not in the sequence

•       iter find_if (iter first, iter last, predicate pred);

–    A predicate is a function that returns T or F

–    Examines [first, last) applying predicate to each element; If pred returns true, the search ends, returning an iterator to the element

•       void for_each (iter first, iter last, function);

–    Applies the function to each element of the container

•       iter max_element (iter first, iter last);

–    Returns an iterator to the maximum element within the range

•       iter sort (iter first, iter last);

–    Sorts the specified range

 

Member functions vs. global algorithms

–    Often a container has a member function that does the same thing as an algorithm, but with much better performance

•       An example is the global remove( ) algorithm

–    remove( ) reorders the elements by changing their values

–    So if the first element is removed, then all the following elements are assigned to their previous elements

–    This is an extremely inefficient way to remove an element from a linked list, but the only way to remove from an array

•    remove( ) doesn’t know if it is operating on a list…it always does the same thing

•       The list container class provides special member functions for all the algorithms that manipulate elements in the list.

•       For example, global sort( ) will not work with list containers, since it requires a random access iterator.  Instead, use the sort( ) member function.

 

The sequence containers

•      Vectors—implemented as a dynamic array

•      Deques—a double ended queue;

•      Lists – implemented as a doubly linked list

•      In addition, you can use strings and ordinary arrays as sequence containers

 

The vector container--how it is implemented

•       Implemented as a dynamic array(size depends on implementation)

•       To use a vector you must include the header file #include <vector>

•       Vectors provide good performance if you insert or delete elements at the end

–    When you insert or delete in the middle or beginning, every element behind has to be moved to another position

•       The iterators are random access, so you can use any algorithm of the STL

•       Any object that will be stored in a vector must define a default constructor.

•       It must also define the < and == operations

•       You can use array subscripting to access or modify vector elements

–    No range checking done with [ ]

–    Use the at( ) member function for range checking

 

Allocating memory for vectors

•       When you declare a vector, more memory is dynamically allocated than needed to contain all the elements of a vector

•       If your vector grows larger than this amount, reallocation is necessary

–    The entire vector must be copied into a larger space.  Obviously this takes time.

–    It also invalidates all references, pointers and iterators for elements of the vector

•       Size and Capacity

–    the size( ) member function returns the number of elements in your vector

–    the capacity( ) member function returns the number of items a vector could contain without reallocation

–    If you exceed the capacity( ), the vector has to reallocate its internal memory

–    To avoid reallocation, you can use reserve( ) to ensure a certain capacity before you really need it. EX:  v.reserve(80)

 

Deque containers

•      To use a deque you must include the header file #include <deque>

•      Implemented as dynamic arrays, typically a bunch of individual blocks, growing in opposite directions

•      The interface of vectors and deques is almost the same

•      Inserting or deleting at either end of a deque is efficient

•      Inserting or deleting  in the middle of a deque is inefficient, but can be done (same as for vectors)

 

List containers

•      Implemented as a doubly linked list

•      Does not provide random access

–    So no subscript operator nor at( )

–    Cannot use algorithms that require random access iterators

•      No operations for capacity or reallocation

•      Many special member functions for inserting, deleting and moving elements.  They are faster than the global algorithms with the same names.

•      To use a list you must include the header file #include <list>

 

Some Sequential Container member functions

Vectors

push_back( ) --automatically increase vector size if necessary

(cannot use push_front—too inefficient)

size( ) – returns size

max_size ( ) –system dependent

swap ( ) –swap contents of vectors

empty ( ) – returns boolean

back ( ) – return last element

pop_back ( ) - remove last element

insert(iterator, value ) – not too efficient for vectors

erase( iterator) - not efficient

 

Lists

push_back( )

push_front

size( )

front( ) or back( ) – return items

pop_front( ) 

pop_back( )

insert( ) – 3 versions

erase( )

reverse( )

merge( list)

unique( ) – removes duplicates

 

Associative containers

•      Sets & Multisets

–    These containers sort their elements automatically according to a certain sorting criterion

–    The difference is that multisets allow duplicates; sets do not

•      Maps & Multimaps

–    These containers manage key/value pairs as elements

–    They also sort their elements automatically according to some sorting criterion that is used for the key

–    The difference is that maps do not allow duplicates, while multimaps do

•      Pairs

–    The class pair is provided to treat two values as a single unit. 

•    It has two data members, first and second

–    It is used by maps and multimaps to manage their elements