STL List Class

Dr. Mark J. Sebern

Version 1.5


What is the STL? string vector Iterators find

The list container implements a classic list data structure; unlike a C++ array or an STL vector, the objects it contains cannot be accessed directly (i.e., by subscript). (Be sure to study the requirements for objects that are stored in STL containers.) The list container is defined as a template class, meaning that it can be customized to hold objects of any type. Here is a simple example:

#include <list>		// list class library
using namespace std;
...
  // Now create a "list" object, specifying its content as "int".
  // The "list" class does not have the same "random access" capability
  // as the "vector" class, but it is possible to add elements at
  // the end of the list and take them off the front.
  list<int> list1;

  // Add some values at the end of the list, which is initially empty.
  // The member function "push_back" adds at item at the end of the list.
  int value1 = 10;
  int value2 = -3;
  list1.push_back (value1);
  list1.push_back (value2);
  list1.push_back (5);
  list1.push_back (1);

  // Output the list values, by repeatedly getting the item from
  // the "front" of the list, outputting it, and removing it
  // from the front of the list.
  cout << endl << "List values:" << endl;
  // Loop as long as there are still elements in the list.
  while (list1.size() > 0)
  {
    // Get the value of the "front" list item.
    int value = list1.front();
    // Output the value.
    cout << value << endl;
    // Remove the item from the front of the list ("pop_front"
    // member function).
    list1.pop_front();
  } 

Member functions

Some commonly used member functions of the list class are:

size size_type size() const;
Returns the number of items (elements) currently stored in the list. The size_type type is an unsigned integral value.
// Loop as long as there are still elements in the list.
 while (list1.size() > 0)
 {
   ...
 } 
empty bool empty() const;
Returns a true value if the number of elements is zero, false otherwise.
if (list1.empty())
{
  ...
} 
push_back
push_front
void push_back(const T& x);
void push_front(const T& x);
Adds the element x at the end (or beginning) of the list. (T is the data type of the list's elements.)
list<int> nums;
nums.push_back (3);
nums.push_back (7);
nums.push_front (10); // 10 3 7 
front
back
T& front();
const T& front() const;
T& back();
const T& back() const;

Obtain a reference to the first or last element in the list (valid only if the list is not empty). This reference may be used to access the first or last element in the list.
list<int> nums;
nums.push_back(33);
nums.push_back(44);
cout << nums.front() << endl; // 33
cout << nums.back() << endl; // 44 
begin iterator begin();
Returns an iterator that references the beginning of the list.
end iterator end();
Returns an iterator that references a position just past the last element in the list.
insert iterator insert(iterator position, const T& x);
Insert the element x (type T is the type of a list element) into the list at the position specified by the iterator (before the element, if any, that was previously at the iterator's position). The return value is an iterator that specifies the position of the inserted element.
  nums_iter = find (nums.begin(), nums.end(), 15);
  if (nums_iter != nums.end())
  {
    nums_iter = nums.insert (nums_iter, -22);
    cout << "Inserted element " << (*nums_iter) << endl;
  } 
erase void erase(iterator position);
void erase(iterator first, iterator last);
Erase (remove) one element or a range of elements from a list. In the case of a range, this operation deletes elements from the first iterator's position up to, but not including, the second iterator's position. For an alternate way to erase all elements, see clear().
  nums.erase (nums.begin(), nums.end()); // Remove all elements;
...
  nums_iter = find(nums.begin(), nums.end(), 3); // Search the list.
  // If we found the element, erase it from the list.
  if (nums_iter != nums.end()) nums.erase(nums_iter);
clear void clear();
Erase all elements from a list.

nums.clear(); // Remove all elements;

pop_front
pop_back
void pop_front();
void pop_back();

Erases the first (or last) element from a list. These operations are illegal if the list is empty.
  while (list1.size() > 0)
  {
    ...
    list1.pop_front();
  } 
remove void remove (const T& value);
Erases all list elements that are equal to value. The equality operator (==) must be defined for T, the type of element stored in the list.
  nums.remove(15); 
sort void sort();
Sorts the list elements in ascending order. The comparison operator < ("less than") must be defined for the list element type. Note that the STL sort algorithm does NOT work for lists; that's why a sort member function is supplied.
  nums.sort(); 
reverse void reverse();
Reverses the order of elements in the list.
  nums.reverse(); 

In addition to these member functions, some STL algorithms (e.g., find) can be applied to the list container.

Operators

Some of the operators defined for the list container are:

= The assignment operator replaces the target list's contents with that of the source list:
list<int> a;
list<int> b;

a.push_back(5);
a.push_back(10);

b.push_back(3);

b = a;
// The list b now contains two elements: 5, 10 
== Tests whether two lists have the same content (element-by-element comparison for all elements).

Note that there is no subscript operator for the list container, since random access to elements is not supported.

Using iterators with lists

More information on iterators is available. Here, we will consider only a few simple uses of iterators with list containers.

Traversing a list

A simple example of iterator use is traversing a list to print out its elements. The function output_int_list writes the elements of a list to an output stream and appends a specified delimiter string (here, just a newline character) after each element.

The list is passed by constant reference, instead of by value, so that it does not have to be copied (along with all its elements), but is still safe from modification. A const iterator (necessary because the argument is const) is used to traverse the list; each element is written to the specified stream.

#include <list>	 // list class library
using namespace std;
...
  list<int> nums;

  nums.push_back (3);
  nums.push_back (7);
  nums.push_front (10);

  cout << endl << "List 'nums' now is:" << endl;
  output_int_list (nums, cout, "\n");
  cout << endl;
...
void output_int_list (const list<int>& lst,
                      ostream& out_stream,
                      const string& delim)
{
  // Create constant iterator for list.
  list<int>::const_iterator iter;
  // Iterate through list and output each element.
  for (iter=lst.begin(); iter != lst.end(); iter++)
  {
    out_stream << (*iter) << delim;
  }
} 

Accessing adjacent elements

Just as the iterator's increment operator can be used to move forward in a list, the decrement operator may be used to "back up." Here, we search for the first occurrence of a certain element value, and then print the previous and following elements, if they exist. Note that we can copy the value of an iterator to "mark" a list position and that more than one iterator can be associated with a single container.

#include <list>  // list class library
#include <algorithm>	 // STL algorithms class library
using namespace std;
...
  list<int> nums;
  list<int>::iterator nums_iter;

  nums.push_back (3);
  nums.push_back (7);
  nums.push_front (10);

  nums_iter = find(nums.begin(), nums.end(), 3); // Search the list.
  if (nums_iter != nums.end())
  {
    cout << "Number " << (*nums_iter) << " found." << endl; // 3
    // If found element is not first, print out previous.
    if (nums_iter != nums.begin())
    {
     	// Copy "found" iterator, and back up one position.
    	 list<int>::iterator prev_iter = nums_iter;
     	cout << "Previous element is " << (*(--prev_iter)) << endl;
    }

    // Copy "found" iterator position, and move forward one position.
    list<int>::iterator next_iter = nums_iter;
    next_iter++;
    // If we didn't fall off the end, print out next element.
    if (next_iter != nums.end())
    {
     	cout << "Following element is " << (*next_iter) << endl;
    }
  }
  else
  {
    cout << "Number not found." << endl;
  } 

Iterator values may become invalid if the content of the associated container changes. For example, an iterator may specify the position of an element that is subsequently erased; in this case, the iterator value is no longer valid.


This page was last updated on November 24, 1999; send comments to Mark Sebern.