Sequential Containers - PowerPoint PPT Presentation

About This Presentation
Title:

Sequential Containers

Description:

The Copy Constructor, Assignment Operator, and Destructor. Single-Linked Lists and Double-Linked Lists. The list class and the Iterator ... – PowerPoint PPT presentation

Number of Views:45
Avg rating:3.0/5.0
Slides: 100
Provided by: eliot7
Learn more at: https://cse.buffalo.edu
Category:

less

Transcript and Presenter's Notes

Title: Sequential Containers


1
Sequential Containers
  • Based on Koffmann and Wolfgang
  • Chapter 4

2
Chapter Outline
  • Template Classes and the Vector
  • Applications of vector
  • Implementation of the vector class
  • The Copy Constructor, Assignment Operator, and
    Destructor
  • Single-Linked Lists and Double-Linked Lists
  • The list class and the Iterator
  • Implementation of a Double-Linked List Class
  • Applications of the list Class
  • Standard Library Containers
  • Standard Library Algorithms and Function Objects

3
Template Container Classes
  • A template container class is a class that stores
    and processes a collection of information.
  • The type of this information is a parameter that
    is specified when the template class is
    instantiated.
  • Example
  • templatelttypename Tgtclass some_container
  • The parameter T is a placeholder for the actual
    data type.
  • some_containerltItem_Typegt call_lengths // holds
    Item_Type
  • Some_containerltPeoplegt people // holds People

4
The Vector
  • An enhancement of the array.
  • Can be used like an array
  • Access a value via an index
  • x vi
  • vj z
  • Additional capabilities
  • Increase or decrease its length
  • Insert an element at a specified position
  • Remove an element from a specified position

5
Vector Example
  • // Create a vector to hold strings.
  • vectorltstringgt my_vector
  • // Add some entries.
  • my_vector.push_back("Bashful")
  • my_vector.push_back("Awful")
  • my_vector.push_back("Jumpy")
  • my_vector.push_back("Happy")

6
Vector Example (2)
Had to slide 2,3 to 3,4
my_vector.insert(2, Doc)
7
Vector Example (3)
my_vector.push_back("Dopey") // add at end
Cheap to add at end
8
Vector Example (4)
my_vector.erase(1)
Had to slide 2..5 to 1..4
lst.set(1, Sneezy)
Replacement is cheap
9
Example Applications of vector
  • vectorltItem_Typegt some_Item_Types
  • Item_Type nums 5, 7, 2, 15
  • for (size_t i 0 i lt 4 i)
  • some_Item_Types.push_back(numsi)
  • Item_Type sum 0
  • for (size_t i 0 i lt 4 i)
  • sum some_Item_Typesi
  • cout ltlt "sum is " ltlt sum ltlt endl

10
Using vector in PhoneDirectory
  • vectorltDirectory_Entrygt the_directory
  • / Adds a new entry
  • _at_param name The name of the person
  • _at_param new_number The new number
  • /
  • void add(string name, string number)
  • Directory_Entry new_entry(name, number)
  • the_directory.push_back(new_entry)

11
Using vector in PhoneDirectory (2)
  • string Phone_Directoryadd_or_change_entry(const
    string name,
  • const string number)
  • string old_number ""
  • Item_Type index find(name)
  • if (index ! -1)
  • old_number the_directoryindex.get_number()
  • the_directoryindex.set_number(number)
  • else
  • add(name, number)
  • modified true
  • return old_number

12
Implementing a vector Class
  • KWvector simple implementation of stdvector
  • Physical size of array indicated by data field
    current_capacity
  • Number of data items indicated by the data field
    num_items

13
KWvector Fields, Constructor
  • templatelttypename Item_Typegt
  • class vector
  • private
  • // Data fields
  • / The initial capacity of the array /
  • static const size_t INITIAL_CAPACITY
    10
  • / The current capacity of the array /
  • size_t current_capacity
  • / The current num_items of the array
    /
  • size_t num_items
  • / The array to contain the data /
  • Item_Type the_data
  • public
  • // Member Functions
  • / Constructsltigt lt/igtan empty vector with
    the default
  • initial capacity.
  • /
  • vectorltItem_Typegt() current_capacity(INITI
    AL_CAPACITY),
  • the_data(new Item_TypeINITIAL_CAPACITY),
    num_items(0)

14
Implementing vectorpush_back
15
Implementing vectorpush_back (2)
  • void push_back(const Item_Type the_value)
  • // Make sure there is space for the new item.
  • if (num_items current_capacity)
  • // Allocate an expanded array
  • reserve(2 current_capacity)
  • // Insert the new item.
  • the_datanum_items the_value
  • num_items

16
Implementing vectorreserve
  • void reserve(size_t new_capacity)
  • if (new_capacity gt current_capacity)
  • if (new_capacity gt 2 current_capacity)
  • current_capacity new_capacity
  • else
  • current_capacity 2 // Double the
    capacity.
  • Item_Type new_data new Item_Typecurrent_ca
    pacity
  • // Copy the data over.
  • for (size_t i 0 i lt num_items i)
  • new_datai the_datai
  • // Free the memory occupied by the old copy.
  • delete the_data
  • // Now point to the new data.
  • the_data new_data

17
Implementing vectorinsert
18
Implementing vectorinsert (2)
  • void insert(size_t index, const Item_Type
    the_value)
  • // Validate index.
  • if (index gt num_items)
  • throw stdout_of_range
  • ("index to insert is out of range")
  • // Ensure that there is space for the new item.
  • if (num_items current_capacity)
  • reserve(2 current_capacity) // Allocate
    an expanded array
  • // Move data from index to num_items - 1 down.
  • for (size_t i num_items i gt index i--)
  • the_datai the_datai - 1
  • // Insert the new item.
  • the_dataindex the_value
  • num_items

19
Implementing vectorerase
20
Implementing vectorerase (2)
  • void erase(size_t index)
  • // Validate index.
  • if (index gt num_items)
  • throw stdout_of_range
  • ("index to insert is out of range")
  • // Move items below the removed one up.
  • for (size_t i index 1 i lt num_items i)
  • the_datai - 1 the_datai
  • num_items--

21
Implementing vectoroperator
  • Item_Type operator(size_t index)
  • // Verify that the index is legal.
  • if (index lt 0 index gt num_items)
  • throw stdout_of_range
  • ("index to operator is out of range")
  • return the_dataindex

22
The copy constructor
  • The compiler defines a special constructor, known
    as the copy constructor, that constructs a copy
    of a given object.
  • This constructor is automatically invoked when
    objects are passed by value to a function and
    when values are returned.
  • It can also be explicitly invoked. E.G.
  • vectorltItem_Typegt v2(v1)
  • will construct the vector v2 to be a copy of v1.

23
Shallow Copy versus Deep Copy
  • The copy constructor that is automatically
    created by the compiler (known as the default
    copy constructor) makes a copy of each data
    member.
  • Note that the data member the_data in both v1 and
    v2 point to the same array.

24
Shallow Copy after v1.push_back(20)
25
Deep Copy of a Vector
26
Copy Constructor That Makes Deep Copy
  • vectorltItem_Typegt(const vectorltItem_Typegt other)
  • current_capacity(other.capacity),
    num_items(other.num_items),
  • the_data(new Item_Typeother.current_capacit
    y)
  • for (size_t i 0 i lt num_items i)
  • the_datai other.the_datai

27
Destructor
  • When a vector is constructed, space for the data
    array is allocated via the new operator.
  • All space that is allocated with the new operator
    should be returned to the free storage pool via
    the delete operator when it is no longer needed.
  • Failure to return allocated memory results in a
    memory leak and can lead to your program crashing
    because memory is not available.
  • When an object is no longer needed, its
    destructor is called.
  • It is the destructors responsibility to free any
    allocated memory.

28
The vectors destructor
  • virtual vectorltItem_Typegt()
  • delete the_data

29
The swap function
  • The swap function swaps the data fields of two
    vectors.
  • void swap(vectorltItem_Typegt other)
  • stdswap(num_items, other.num_items)
  • stdswap(current_capacity, other.current_capaci
    ty)
  • stdswap(the_data, other.the_data)

30
The assignment operator
  • The statement
  • v2 v1
  • invokes the assignment operator.
  • Like the copy constructor, it should make a deep
    copy.
  • We can use the copy constructor and swap function
    to implement the assignment operator.
  • vectorltItem_Typegt operator(const
    vectorltItem_Typegt other)
  • // Make a copy of the other vector.
  • vectorltItem_Typegt the_copy(other)
  • // Swap contents of self with the copy.
  • swap(the_copy)
  • // Return -- upon return the old value will be
    destroyed.
  • return this

31
The Rule of Three
  • A class that dynamically allocates memory (or
    other resources) should define
  • A copy constructor
  • A destructor
  • An assignment operator
  • Corollary If a class defines one of
  • Copy constructor
  • Destructor
  • Assignment operator
  • then it should define all three.

32
Performance of the vector Class
  • Index operator executes in constant time O(1)
  • Inserting or removing general elements is linear
    time O(n)
  • Adding at end is (usually) constant time O(1)
  • With our reallocation policy the average is O(1)
  • The worst case is O(n) because of reallocation

33
Singly-Linked Lists and Doubly-Linked Lists
  • The vector insert and erase methods are O(n)
  • Because they need to shift the underlying array
  • Linked list overcomes this
  • Add/remove items anywhere in constant time O(1)
  • Each element (node) in a linked list stores
  • The element information, of type Item_Type
  • A link to the next node
  • A link to the previous node (optional)

34
A List Node
  • A node contains
  • A data item
  • One or more links
  • A link is a pointer to a list node
  • The node class is usually defined inside another
    class
  • It is a hidden inner class
  • The details of a node should be kept private

35
List Nodes for Singly-Linked Lists
36
List Nodes for Singly-Linked Lists
  • ifndef NODE_H_
  • define NODE_H_
  • / A Node is the building block for a
    single-linked list. /
  • struct Node
  • // Data Fields
  • / The data /
  • Item_Type data
  • / The pointer to the next node. /
  • Node next
  • // Constructor
  • / Creates a new Node that points to another
    Node.
  • _at_param data_item The data stored
  • _at_param next_ptr pointer to the Node that is
  • pointed to by the new Node
  • /
  • Node(const Item_Type data_item, Node next_ptr
    NULL)
  • data(data_item), next(next_ptr)

37
struct versus class
  • A struct is the same as a class.
  • Except that the default visibility for a struct
    is public.
  • Generally structs are used to define classes that
    only contain public data fields.
  • Constructors may be provided.
  • Other member functions (operators) are usually
    not defined for structs.

38
Inserting a Node into a Single Linked List
Node bob new Node("Bob") bob-gtnext
harry-gtnext // step 1 harry-gtnext bob // step
2
39
Removing a node from a single-linked list
Node ptr tom-gtnext tom-gtnext
tom-gtnext-gtnext delete ptr
40
Doubly-Linked Lists
  • Limitations of a singly-linked list include
  • Can insert only after a referenced node
  • Removing node requires pointer to previous node
  • Can traverse list only in the forward direction
  • We can remove these limitations
  • Add a pointer in each node to the previous node
    doubly-linked list

41
Doubly-Linked Lists, The Diagrams
42
Inserting into a Double-Linked List
DNode sharon new DNode("Sharon") // Link new
DNode to its neighbors sharon-gtnext sam //
Step 1 sharon-gtprev sam-gtprev // Step 2
43
Inserting into a Double-Linked List (2)
// Link old predicessor of sam to new
predicessor. sam-gtprev-gtnext sharon // Step
3 // Link to new predicessor. sam-gtprev sharon
// Step 4
44
Removal from a Double-Linked List
harry-gtprev-gtnext harry-gtnext // Step
1 harry-gtnext-gtprev harry-gtprev // Step
2 delete harry
45
Circular Lists
  • Circular doubly-linked list
  • Link last node to the first node, and
  • Link first node to the last
  • Advantages
  • Can easily keep going past ends
  • Can visit all elements from any starting point
  • Can never fall off the end of a list
  • Disadvantage code must avoid infinite loop!
  • Can also build singly-linked circular lists
  • Traverse in forward direction only

46
Implementing a Circular List
47
The iterator
  • Suppose we want to access each element of a list
    in a loop
  • for (Item_Type index 0 index lt a_list.size()
    index)
  • // Do something with next_element, the element
  • // at position index
  • Item_Type next_element a_listindex // not
    valid
  • The subscripting operator (operator) is not
    defined for the list class.
  • Instead an iterator is used to access elements in
    a list.

48
The iterator (2)
49
Using an Iterator
  • We use an iterator like a pointer.
  • // Access each list element and process it
  • for (listltItem_Typegtiterator iter
    a_list.begin()
  • iter ! a_list.end() iter)
  • // Do something with next element (iter)
  • Item_Type next_element iter
  • . . .

50
Notes on using iterators in loops
  • We test for the end of the loop with the
    expression
  • iter ! a_list.end()
  • The order of individual iterator values is not
    meaningful.Thus iter lt a_list.end() is not a
    meaningful test.
  • We increment the iterator using the expression
  • iter
  • The postfix increment operator saves the
    previous value and then performs the increment.
    Since this previous value is not used, it is
    more efficient to use the prefix increment
    operator.

51
iterator versus const_iterator
  • Each standard library container (e.g. the list)
    provides both an
  • iterator
  • and a
  • const_iterator
  • The operations on them are the same, except
  • When a const_iterator is dereferenced
    (operator), the value of the item referenced
    cannot be changed.

52
Iterator Hierarchy
53
Iterator Functions
54
The list class
  • Part of the C Standard Library

55
Implementing KWlist
  • templatelttypename Item_Typegt
  • class list
  • private
  • // Insert definition of nested class
    DNode here.
  • include "DNode.h"
  • public
  • // Insert definition of nested class
    iterator here.
  • include "list_iterator.h"
  • // Give iterator access to private
    members of list.
  • friend class iterator
  • // Insert definition of nested class
    const_iterator here.
  • include "list_const_iterator.h"
  • // Give const_iterator access to private
    members of list.
  • friend class const_iterator
  • private
  • // Data fields
  • / A reference to the head of the list
    /
  • DNode head
  • / A reference to the end of the list /

56
The no-argument constructor
  • / Construct an empty list. /
  • list() head(NULL), tail(NULL), num_items(0)

57
The Copy Constructor
  • / Construct a copy of a list. /
  • list(const listltItem_Typegt other) list()
    head(NULL),
  • tail(NULL), num_items(0)
  • for (const_iterator itr other.begin()
  • itr ! other.end() itr)
  • push_back(itr)

58
The Destructor
  • / Destroy a list. /
  • list()
  • while (head ! NULL)
  • DNode current head
  • head head-gtnext
  • delete current
  • tail NULL
  • num_items 0

59
The Assignment Operator
  • / Assign the contents of one list to another.
    /
  • listltItem_Typegt operator(const listltItem_Typegt
    other)
  • // Make a copy of the other list.
  • listltItem_Typegt temp_copy(other)
  • // Swap contents of self with the copy.
  • swap(temp_copy)
  • // Return -- upon return the old value will be
    destroyed.
  • return this

60
The push_front function
  • void push_front(const Item_Type item)
  • head new DNode(item, NULL, head) // Step 1
  • if (head-gtnext ! NULL)
  • head-gtnext-gtprev head // Step 2
  • if (tail NULL) // List was empty.
  • tail head
  • num_items

61
Adding to the Head of the list
62
The push_back function
  • void push_back(const Item_Type item)
  • if (tail ! NULL)
  • tail-gtnext new DNode(item, tail, NULL) //
    Step 1
  • tail tail-gtnext // Step 2
  • num_items
  • else // List was empty.
  • push_front(item)

63
Adding to the Tail of the list
64
The insert function
  • iterator insert(iterator pos, const Item_Type
    item)
  • // Check for special cases
  • if (pos.current head)
  • push_front(item)
  • return begin()
  • else if (pos.current NULL) // Past the
    last node.
  • push_back(item)
  • return iterator(this, tail)
  • // Create a new node linked before node
    referenced by pos.
  • DNode new_node new DNode(item,
  • pos.current-gtprev,
  • pos.current) //
    Step 1
  • // Update links
  • pos.current-gtprev-gtnext new_node // Step
    2
  • pos.current-gtprev new_node // Step
    3
  • num_items
  • return iterator(this, new_node)

65
Adding to the Middle of the list
66
The pop_front Function
  • void pop_front()
  • if (head NULL)
  • throw stdinvalid_argument
  • ("Attempt to call pop_front() on an empty
    list")
  • DNode removed_node head
  • head head-gtnext
  • delete removed_node
  • if (head ! NULL)
  • head-gtprev NULL
  • else
  • tail NULL
  • num_items--

67
The pop_back Function
  • void pop_back()
  • if (tail NULL)
  • throw stdinvalid_argument
  • ("Attempt to call pop_back() on an empty
    list")
  • DNode removed_node tail
  • tail tail-gtprev
  • delete removed_node
  • if (tail ! NULL)
  • tail-gtnext NULL
  • else
  • head NULL
  • num_items--

68
The erase Function
  • iterator erase(iterator pos)
  • if (empty())
  • throw stdinvalid_argument ("Attempt to call
    erase on an empty list")
  • if (pos end())
  • throw stdinvalid_argument ("Attempt to call
    erase of end()")
  • // Create an iterator that references the
    position following pos.
  • iterator return_value pos
  • return_value
  • // Check for special cases.
  • if (pos.current head)
  • pop_front()
  • return return_value
  • else if (pos.current tail)
  • pop_back()
  • return return_value
  • else // Remove a node in the
    Item_Typeerior of the list.
  • // Unlink current node.
  • DNode removed_node pos.current
  • removed_node-gtprev-gtnext removed_node-gtnext

69
The kwlistltItem_Typegtiterator
70
Data Fields and The Constructor
  • class iterator
  • // Give the parent class access to this class.
  • friend class listltItem_Typegt
  • private
  • // Data fields
  • / A reference to the parent list /
  • listltItem_Typegt parent
  • / A pointer to the current DNode /
  • typename listltItem_TypegtDNode current
  • // Member functions
  • / Constructs an iterator that references a
    specific DNode.
  • Note this constructor is private. Only the
    list class
  • can create one from scratch.
  • _at_param my_parent A reference to the list
  • _at_param position A pointer to the current
    DNode
  • /
  • iterator(listltItem_Typegt my_parent, DNode
    position)
  • parent(my_parent), current(position)

71
Dereferencing Operators
  • / Returns a reference to the currently
    referenced item.
  • _at_return A reference to the currently
    referenced item
  • _at_throws stdinvalid_argument if this
    iterator is at end
  • /
  • Item_Type operator() const
  • if (current NULL)
  • throw stdinvalid_argument("Attempt to
    dereference end()")
  • return current-gtdata
  • / Returns a pointer to the currently
    referenced item.
  • Item_Type must be a class or struct. This
    restriction
  • is enforced by the compiler.
  • _at_return A pointer to the currently
    referenced item
  • _at_throws stdinvalid_argument If this
    iterator is at end
  • /
  • Item_Type operator-gt() const
  • if (current NULL)
  • throw stdinvalid_argument("Attempt to
    dereference end()")

72
Prefix increment and decrement
  • iterator operator()
  • /ltsnippet id"5" omit"false"gt/
  • if (current NULL)
  • throw stdinvalid_argument("Attempt to
    advance past end()")
  • current current-gtnext
  • return this
  • iterator operator--()
  • if (current parent-gthead)
  • throw stdinvalid_argument("Attempt to
    move before begin()")
  • if (current NULL) // Past last element.
  • current parent-gttail
  • else
  • current current-gtprev
  • return this

73
Postfix increment and decrement
  • iterator operator(Item_Type)
  • // Make a copy of the current value.
  • iterator return_value this
  • // Advance self forward.
  • (this)
  • // Return old value.
  • return return_value // Return the value
    prior to increment
  • iterator operator--(Item_Type)
  • // Make a copy of the current value.
  • iterator return_value this
  • // Move self backward.
  • --(this)
  • // Return old value.
  • return return_value // Return the value
    prior to decrement

74
The const_iterator
  • Identical to the iterator except that the
    dereferencing operators are defined as follows
  • const Item_Type operator() const
  • if (current NULL)
  • throw stdinvalid_argument
  • ("Attempt to dereference end()")
  • return current-gtdata
  • const Item_Type operator-gt() const
  • if (current NULL)
  • throw stdinvalid_argument
  • ("Attempt to dereference end()")
  • return (current-gtdata)

75
An Application Ordered Lists
  • Want to maItem_Typeain a list of names
  • Want them in alphabetical order at all times
  • Approach Develop an Ordered_List class
  • For reuse, good if can work with other types

76
Design of the Ordered_List class
77
Algorithm for Insertion
  • Find the first item in the list that is greater
    than or equal to the item to be inserted.
  • Insert the new item before this one.

78
Refinement of algorithm
  • 1.1 Create an iterator that starts at the
    beginning of the list
  • 1.2 while the iterator is not at the end, and the
    item at the iterator position is less than the
    item to be inserted
  • 1.3 Advance the iterator
  • 2. Insert the new item before the current
    iterator position

79
Inserting "Bill" before "Caryn"
80
Ordered_Listinsert
  • void insert(const Item_Type an_item)
  • typename stdlistltItem_Typegtiterator itr
  • a_list.begin()
  • while (itr ! a_list.end() itr lt an_item)
  • itr
  • // itr points to the first item gt an_item or
    the end.
  • a_list.insert(itr, an_item)

81
Standard Library Containers
82
Common Requirements for Containers
83
Common Requirements for Sequences
84
Requirements Applicable to Some Sequences
85
The Standard Library Algorithms
  • Function to find an Item_Type in a
    listltItem_Typegt
  • listltItem_Typegtiterator find(listltItem_Typegt
    a_list, Item_Type target)
  • for (listltItem_Typegtiterator itr
    a_list.begin()
  • itr ! a_list.end() itr)
  • if (itr target)
  • return itr
  • return a_list.end()
  • Observe that this function only works for
    Item_Type.

86
Template version of find
  • template lttypename Item_Typegt
  • listltItem_Typegtiterator find(listltItem_Typegt
    a_list,
  • const Item_Type
    target)
  • typedef typename listltItem_Typegtiterator
    iterator
  • for (iterator itr a_list.begin() itr !
    a_list.end()
  • itr)
  • if (itr target)
  • return itr
  • return a_list.end()
  • This only works for a vector.
  • What if we want to search a list?

87
General Version of find
  • template lttypename Iterator, typename Item_Typegt
  • Iterator find(Iterator first, Iterator last,
  • const Item_Type target)
  • while (first ! last)
  • if (first target)
  • return first
  • return first
  • first references the first item in the sequence
  • last references one past the last item in the
    sequence

88
The algorithm library
  • The standard library header ltalgorithmgt defines
    several template functions.
  • These perform fairly standard operation on
    sequences within containers
  • find an item (find)
  • apply a function to each item (for_each)
  • copy values from one container to another (copy)
  • sort the contents of a container (sort)

89
Why use algorithm library
  • Most of the algorithms in ltalgorithmgt are fairly
    simple.
  • Why not code them in-line in your program
    yourself?
  • No need to reinvent the wheel
  • While they are fairly simple, they have all been
    thoroughly tested.
  • Compiler can generate more optimal code from
    standard library

90
Selected Members of ltalgorithmgt
91
(No Transcript)
92
(No Transcript)
93
Copy one a list to a vector
  • a_vector.resize(a_list.size())
  • copy(a_list.begin(), a_list.end(),
    a_vector.begin())

94
A more complicated example
  • // Sort a vector
  • sort(a_vector.begin(), a_vector.end())
  • // Accumulate the sum
  • int sum accumulate(a_vector.begin(),
    a_vector.end(), 0)
  • cout ltlt "Sum is " ltlt sum ltlt endl
  • // Check first element to see if it is the
    smallest
  • if (a_vector.begin() !
  • min_element(a_vector.begin(),
    a_vector.end())
  • cerr ltlt "Error in sort\n"
  • // Check last element to see if it is the largest
  • if (--a_vector.end() !
  • max_element(a_vector.begin(),
    a_vector.end())
  • cerr ltlt "Error in sort\n"

95
Specializing the swap function
  • Swap is defined as
  • template lttypename Tgt
  • void swap(T x, T y)
  • T temp(x) // Make copy of x
  • x y
  • y temp
  • What if we call this with
  • swap(vector1, vector2)
  • This will expand to
  • vectorltintgt temp(vector1) //Make a copy of
    vector 1
  • vector1 vector2 //Make a copy of
    vector 2
  • vector2 temp //Make a copy of temp

96
Specializing swap (2)
  • The vector (and all other containers) define a
    member function swap that swaps the contents
    without copying.
  • Therefore, we need to define a swap function for
    vector (and the other containers) that will call
    this member function
  • templatelttypename Item_Typegt
  • inline void swap(vectorltItem_Typegt x,
  • vectorltItem_Type y)
  • x.swap(y)
  • Then the call
  • swap(vector1, vector2)
  • will expand to
  • vector1.swap(vector2)
  • This is called a template specialization
  • The definition is placed in the ltvectorgt header.
  • A specialization of swap is defined for each
    container.

97
Function Objects
  • If f is a function, then the expression
  • f(x)
  • will call this function with the parameter x.
  • A class may overload the function call operator
    (operator()).
  • class Divisible_By
  • private
  • int divisor
  • public
  • Divisible_By(int x) divisor(x)
  • bool operator()(int x)
  • return x divisor 0
  • A class that defines operator() is known as a
    function class.
  • An object of a function class is known as a
    function object.
  • A function object can be used like a function.

98
The find_if function
  • Recall the find function searched a container for
    a target value.
  • The find_if funciton searches a container for a
    value that satisfies a given condition
    (predicate)
  • templatelttypename Iterator, typename Pgt
  • Iterator find_if(Iterator first, Iterator last, P
    pred)
  • while (first ! last)
  • if (pred(first))
  • return first
  • first
  • return first

99
Using find_if and Divisible_By
  • // Find the first number divisible by 3
  • listltintgtiterator iter
  • iter find_if(list_1.begin(), list_1.end(),
    Divisible_By(3))
  • if (iter ! list_1.end())
  • cout ltlt "First number divisible by 3 is " ltlt
    iter ltlt endl
  • else
  • cout ltlt "No number is divisible by 3\n"
  • // Find the first number divisible by 5
  • iter find_if(list_1.begin(), list_1.end(),
    Divisible_By(5))
  • if (iter ! list_1.end())
  • cout ltlt "First number divisible by 5 is " ltlt
    iter ltlt endl
  • else
  • cout ltlt "No number is divisible by 5\n"
  • // Find the first number divisible by 3
Write a Comment
User Comments (0)
About PowerShow.com