What are the problems with my List<T> implementation?
I created a small implementation of the container list that performs certain functions based on a test main()
I was given.
I wanted to add some extra functions to it. Mainly an operator[]
, and a reverse()
function that displays the numbers in the list backwards.
Here is my code, everything with a comment was added to it yesterday.
#include <iostream>
#include <algorithm>
using namespace std;
template <class T> class Link;
template <class T> class List_iterator;
template <class T> class Reverse_iterator;
template <class T>
class List
{
public:
typedef List_iterator<T> iterator;
List();
List(const List<T> & l);
~List();
bool empty() const;
unsigned int size() const;
T & back() const;
T & front() const;
void push_front(const T & x);
void push_back(const T & x);
void pop_front();
void pop_back();
iterator begin() const;
iterator end() const;
iterator rbegin() const;//REVERSE BEGIN
iterator rend() const; //REVERSE END
void insert(iterator pos, const T & x);
void erase(iterator & pos);
List<T> & operator=(const List<T> & l);
List<T> & operator[] (unsigned int x);//OPERATOR []
iterator reverse() const; //REVERSE
protected:
Link<T> * first_link;
Link<T> * last_link;
unsigned int my_size;
};
template <class T>
List<T>::List()
{
first_link = 0;
last_link = 0;
my_size = 0;
}
template <class T>
List<T>::List(const List & l)
{
first_link = 0;
last_link = 0;
my_size = 0;
for (Link<T> * current = l.first_link; current != 0; current = current -> next_link)
push_back(current -> value);
}
template <class T>
typename List<T>::iterator List<T>::begin() const
{
return iterator(first_link);
}
template <class T>
typename List<T>::iterator List<T>::end() const
{
return iterator (last_link);
}
//RBEGIN
template <class T>
typename List<T>::iterator List<T>::rbegin() const
{
return iterator (last_link);
}
//REND
template <class T>
typename List<T>::iterator List<T>::rend() const
{
return iterator(first_link);
}
template <class T>
class Link
{
private:
Link(const T & x): value(x), next_link(0), prev_link(0) {}
T value;
Link<T> * next_link;
Link<T> * prev_link;
friend class List<T>;
friend class List_iterator<T>;
};
template <class T> class List_iterator
{
public:
typedef List_iterator<T> iterator;
List_iterator(Link<T> * source_link): current_link(source_link) { }
List_iterator(): current_link(0) { }
List_iterator(List_iterator<T> * source_iterator): current_link(source_iterator.current_link) { }
T & operator*();
iterator & operator=(const iterator & rhs);
bool operator==(const iterator & rhs) const;
bool operator!=(const iterator & rhs) const;
iterator & operator++();
iterator operator++(int);
iterator & operator--();
iterator operator--(int);
protected:
Link<T> * current_link;
friend class List<T>;
};
template <class T>
T & List_iterator<T>::operator*()
{
return current_link -> value;
}
template <class T>
List_iterator<T> List_iterator<T>::operator++(int)
{
}
template <class T>
List_iterator<T> & List_iterator<T>::operator--()
{
current_link = current_link -> prev_link;
return * this;
}
template <class T>
List_iterator<T> & List_iterator<T>::operator=(const iterator & rhs)
{
///???
}
template <class T>
List_iterator<T> List_iterator<T>::operator--(int)
{
}
template <class T>
List_iterator<T> & List_iterator<T>::operator++()
{
current_link = current_link -> next_link;
return *this;
}
template <class T>
void List<T>::push_back(const T & x)
{
Link<T> * new_link = new Link<T> (x);
if (first_link == 0)
first_link = last_link = new_link;
else
{
new_link->prev_link = last_link;
last_link->next_link = new_link;
last_link = new_link;
}
my_size++;
}
template <class T>
List <T>::~List()
{
Link <T> * first = first_link;
while (first != 0)
{
Link <T> * next = first->next_link;
delete first;
first = next;
}
}
template<class T>
bool List_iterator<T>::operator==(const iterator & rhs) const
{
return ( this->current_link == rhs.current_link );
}
template <class T>
bool List_iterator<T>::operator!=(const iterator & rhs) const
{
return !( *this == rhs );
}
//REVERSE ITERATOR
template <class T> class Reverse_iterator
{
public:
typedef Reverse_iterator<T> riterator;
Reverse_iterator(Link<T> * source_link): current_link(source_link) { }
Reverse_iterator(): current_link(0) { }
Reverse_iterator(List_iterator<T> * source_iterator): current_link(source_iterator.current_link) { }
T & operator*();
riterator & operator=(const riterator & rhs);
bool operator==(const riterator & rhs) const;
bool operator!=(const riterator & rhs) const;
riterator & operator++();
riterator operator++(int);
riterator & operator--();
riterator operator--(int);
protected:
Link<T> * current_link;
friend class List<T>;
};
template <class T>
T & Reverse_iterator<T>::operator*()
{
return current_link -> value;
}
template <class T>
Reverse_iterator<T> Reverse_iterator<T>::operator++(int)
{
}
template <class T>
Reverse_iterator<T> & Reverse_iterator<T>::operator--()
{
current_link = current_link -> next_link;
return * this;
}
template <class T>
Reverse_iterator<T> & Reverse_iterator<T>::operator=(const riterator & rhs)
{
//???
}
template <class T>
Reverse_iterator<T> Reverse_iterator<T>::operator--(int)
{
}
template<class T>
bool Reverse_iterator<T>::operator==(const riterator & rhs) const
{
return ( this->current_link开发者_运维百科 == rhs.current_link );
}
template <class T>
bool Reverse_iterator<T>::operator!=(const riterator & rhs) const
{
return !( *this == rhs );
}
//REVERSE FUNCTION
template <class T>
List_iterator<T> List<T>::reverse() const
{
iterator i, j;
i = begin();
j = end();
for(; i != j; j++, j--)
{
T value = *j;
*j = *i;
*i = value;
}
}
//OPERATOR []
template <class T>
List<T> & List<T>:: operator[] (unsigned int x)
{
Link<T> * current = first_link;
for(int i = 0; i != x && i < my_size; i++)
current = current -> next_link;
return current -> value;
delete current;
}
//REVERSE ITERATOR OPERATOR ++()
template <class T>
Reverse_iterator<T> & Reverse_iterator<T>::operator++()
{
current_link = current_link -> prev_link;
return *this;
}
int main()
{
List<int> l;
l.push_back(44);
l.push_back(33);
l.push_back(11);
l.push_back(22);
List<int> m(l);
cout << "This is the original list" << endl;
List<int>::iterator original(m.begin());
while (original != m.end()) {
cout << *original << endl;
++original;
//cout << l[4]; //Not working
//m.reverse();
//cout << m;//Also Not working
}
}
I am looking for help in:
- Writing my
operator=()
function, which is currently blank. - Understanding why the last few lines in
main()
are not working (I know they are commented out) by going over myoperator[]
definition and myreverse()
function.
Thanks in advance.
Regarding List<T>::operator[]
I believe the main problem with your operator[]
is that it's return type is List<T>&
rather than T&
. You want your operator[]
to return a reference to a T
, not a reference to an entire list. Operator<<
has no idea how to deal with a List<T>
, so it complains.
Additionally:
That
delete
inoperator[]
is unreachable code. (As well as being wrong behaviour - why would you want to delete the link?)Your
operator[]
generates a couple of warnings becausei
is anint
andmy_size
isunsigned
. Easily corrected, see below.Consider what happens if, as @stefaanv has mentioned, someone asks for myList[4] when there are only 4 items in the list (collections index from zero, remember, so [4] is the fifth item. In your current logic, myList[3] would be returned instead - look carefully at the conditions in the for loop.
Here's what I think operator[]
should look like:
template <class T>
T& List<T>:: operator[] (unsigned int x)
{
if(x > (my_size - 1)
|| x < 0)
{
// throw a suitable exception - index out of bounds
}
Link<T> * current = first_link;
for(unsigned int i = 0; i != x && i < my_size; i++)
current = current -> next_link;
return current -> value;
}
...and see here on IdeOne.
Regarding List<T>::reverse
First things first - to see the errors from List_iterator<T> List<T>::reverse()
, you first need to fix your main()
:
//m.reverse();
//cout << m;//Also Not working
Note that m is of type List<int>
, so that cout
line is trying to invoke the << opertaor on your List<T>
class - but there isn't one, so you get errors. You could fix this either by:
- Defining
operator<<
on yourList<T>
class - Replacing the
cout
line with a loop similar to the while loop inmain()
, which iterates through the list item by item.
Once you do one or the other of those, you'll see the real error messages coming from your reverse() function. For one thing, you've declared reverse as returning a List_iterator<T>
- but it currently doesn't return anything!
Hope that helps! Good luck.
iterator begin() const;
iterator end() const;
iterator rbegin() const;//REVERSE BEGIN
iterator rend() const; //REVERSE END
I don't think you've to make these functions const.
It's better if you write two sets of these functions, one for non-const and other for const object.
//first set for non-const objects!
iterator begin();
iterator end();
iterator rbegin();
iterator rend();
//second set for const objects!
const_iterator begin() const;
const_iterator end() const;
const_iterator rbegin() const;
const_iterator rend() const;
This is the C++ Standard way of defining begin
and end
functions!
errors in reverse:
j = end();
end() should points after the container, so j should have an extra decrement if the container is not empty.
for(; i != j; j++, j--)
- j++ must be i++
- for even numbers of elements, i will never be the same a j, use i > j
errors in main:
cout << l[4];
There are only 4 elements in your list and you're referencing the 5th, so this shouldn't work.
精彩评论