Using the C++ Container List
Writing a C++ Container - Part 6
The C++ Container List in Action
Forward: In this part of the series I show you how to put the list, element and iterator together, and how to use them.
By: Chrysanthus Date Published: 11 Oct 2012
Introduction
Compiling
In this project, there are two files called, "listMain.cpp" and "list.hh". "listMain.cpp" is the main file and "list.hh" is the header file. "listMain.cpp" has the main function and all the using code is in the main function. There is an include directive for the header file in the main file.
Template Code in same File
The class template declarations, the synopses and the implementations of the synopses are in one file, the header file, in this project. C++ does not allow template code parts to be in different files.
Running the Application
For my compiler, the following command runs the application at my DOS (command) prompt of my working directory.
g++ listMain.cpp -o listUsing.exe
Here, "listUsing.exe" is the resulting executable file. You can choose any name you want for "listUsing". The resulting "listUsing.exe" file is saved automatically in the working directory.
"listUsing.exe" is the result of compilation and not part of the compilation process.
Hey, the typical,
#include <iostream>
using namespace std;
has to be in the main file.
Using the List
In the project I use the list and its features (elements and iterator) in the main function of the main file. Everything below is in that light. To use the list, you must instantiate the list and you must also instantiate the iterator. Any element in the list is instantiated by the list code for you. The name of the list is, TempList and the name of the iterator is, TempIterator.
For the rest of this tutorial, we shall test some of the methods and operators of the list and iterator.
In the following program a list and an iterator are instantiated independently and then the association between the list and iterator is made:
#include <iostream>
using namespace std;
#include <list.hh>
int main()
{
TempList<float> lst;
TempIterator<float> iter;
iter = lst.begin();
lst.push_back(1.1);
lst.push_back(2.2);
lst.push_back(3.3);
lst.push_back(4.4);
for (TempIterator<float> p = lst.begin(); p; ++p)
{
cout << *p << '\n';
}
return 0;
}
The first statement in the main function instantiates a list using the default constructor for the list. The second statement in main instantiates an iterator using the default constructor of the iterator. The iterator is of type, TempIterator<float> with "float" because the iterator will be associated to a list of floats.
The third statement in main does the association as follows:
The expression,
lst.begin()
returns an iterator whose pointer (ElementPtr) points to the first element of the list. This iterator is assigned to the iterator, iter, changing the content (data members) of iter. iter is the iterator of interest and it is the one that is used by the list to push_back (add) values to the list. Remember, a value is added automatically with its element. The assignment operator used in this statement is automatically the overloaded assignment operator of the iterator; the left and right operands are iterators of the same class.
The list push_back() calls add values (elements) to the list, giving the list a size of 4.
The for-loop runs through the list displaying the values in the list. The initialization statement of the for-loop is:
TempIterator<float> p = lst.begin();
Again, the assignment operator here, is the overloaded one. The right operand creates a new iterator that points to the first element of lst. The return iterator is assigned to yet a new iterator, p. p in this case is associated to lst.
The while-condition of the loop is just:
p
Remember the cast bool operator defined for the iterator class? This is it in action. As long as p is pointing to an element in the list, it will result in true. Whenever p points to the sentinel, which is null, p results in false.
The increment expression (statement) of the loop is:
++p
This is the overloaded iterator increment operator (prefix). When executed, it points to the next element. Normally, it is a pointer that would point to the next element in an array, when incremented. If you want an iterator to point to the next element, you have to overload the increment operator, to mimic a pointer. Inside the overloaded definition, a pointer is given the address of the next element (not incremented) - see previous parts of the series.
The dereference operator in the loop-block that returns the value the iterator is pointing to, is the overloaded one. It was designed to mimic that (standard) of the pointer. Most of the operators of the loop are overloaded iterator operators.
The iterator class has a constructor that takes a list as argument and so does association during instantiation. The list should have been instantiated. The iterator pointer points to the first element of the list. This constructor should be used when the list has at least one element. The following program illustrates this:
#include <iostream>
using namespace std;
#include <list.hh>
int main()
{
//create list
TempList<float> lst;
//add elements
lst.push_back(1.1);
lst.push_back(2.2);
lst.push_back(3.3);
lst.push_back(4.4);
//create and associate iterator
TempIterator<float> iter(lst);
//point to third element
++iter;
++iter;
//insert value (element)
TempIterator<float> iterIns = lst.insert(iter, 33.33);
//display all values in list
for (TempIterator<float> p(lst.begin()); p; ++p)
{
cout << *p << '\n';
}
cout << '\n';
//erase new fourth element
lst.erase(iterIns);
//display all values in list
for (TempIterator<float> p(lst.begin()); p; ++p)
{
cout << *p << '\n';
}
return 0;
}
The next code segment increments the iterator twice to point to the third element of the list. The statement after inserts a new value (element) just above the third element using the incremented iterator, iter.
The for-loop after, displays all the values present in the list. The next code segment is one line. It erases the inserted element using the iterator returned by the insert() member function. The last code segment displays the resulting set of values in the list.
The initialization statement of each of the for-loop, uses the copy constructor of the iterator. The expression, "lst.begin()" results in a new iterator pointing to the first element of the list. The content of this iterator is copied to p.
End of Tutorial
This is the end of the tutorial. I hope you can now use the C++ Container List Element. Using the other C++ containers is similar to using the list. However, there are a few things you still have to learn in order to maximize their use. It is not difficult to learn how to use them once you know how to use the list. If you have been reading the tutorials of this volume (C++ Course), then you should already know how to use them. Click the "C++ Course" link below to confirm this.
End of Series
I hope you have appreciated this series. The aim is to enable you write your own C++ container. If you want a C++ container, you can choose from, deque, list, queue, stack, map, set or bitset. If you cannot choose from any of these, then you have to write your own. The project we have carried out in the whole series, has re-written the Stantard C++ Container List, with a bit of simplification. The knowledge gained can be used to write a container that is not among the standard containers (deque, list, etc.).
I assume you have completed this series. It means you already had the professional skills in C++. Now, you are in an advanced course of C++. You may already be working. If you ever have too much work, you can subcontract (outsource) some or all to someone in the site below.
Chrys
Related Courses
C++ CourseRelational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem