我正在尝试编写像std :: list one这样的列表模板。 这是我在List.h中的代码:
#include <memory>
#include <cassert>
#include <iterator>
template<typename T, class Node>
class iterator : public std::iterator<std::bidirectional_iterator_tag, Node *, Node &> {
Node *underlying;
public:
explicit iterator(Node *n) : underlying(n) { };
iterator() : underlying(nullptr) { };
iterator &operator++() { //preinc
assert(underlying != nullptr && "Out-of-bounds iterator increment!");
underlying = underlying->next;
return *this;
}
iterator operator++(int) { //postinc
assert(underlying != nullptr && "Out-of-bounds iterator increment!");
iterator temp(*this);
++(*this);
return temp;
}
iterator &operator--() { //predec
assert(underlying != nullptr && "Out-of-bounds iterator decrement!");
underlying = underlying->previous;
return *this;
}
iterator operator--(int) { //postdec
assert(underlying != nullptr && "Out-of-bounds iterator decrement!");
iterator temp(*this);
--(*this);
return temp;
}
bool operator==(const iterator &rhs) {
return underlying == rhs.underlying;
}
bool operator!=(const iterator &rhs) {
return underlying != rhs.underlying;
}
T &operator*() {
return underlying->data;
}
};
template<typename T>
class List {
class Node {
public:
T data;
Node *previous;
Node *next; //is that T needed?
Node(T &d) : data(d) { };
};
private:
Node *head; //first element
Node *tail;
void create() { head = tail = NULL; }
void create(const List &rhs) {
iterator this_iter = head;
iterator rhs_iter = rhs.head;
while (rhs_iter != NULL) {
this_iter->data = (rhs_iter++)->data;
++this_iter;
}
};
public:
typedef T *iterator;
typedef const T *const_iterator;
typedef size_t size_type;
typedef T value_type;
List() { create(); };
List &operator=(const List &rhs) {
if (&rhs != this) {
create(rhs);
}
return *this;
};
List(const List &rhs) { create(rhs); };
~List() { while(head) remove(head); };
T *begin() { return head; };
T *end() { return tail; };
T front() { return head->data; };
T back() { return tail->data; };
bool empty() { return head == NULL; }
size_type size() {
size_t i = 0;
Node *node = head;
while (node) {
node = node->next;
i++;
}
return i;
};
T &operator[](size_type i) {
if (i < size() && i >= 0) {
Node *temp = head;
while (i > 0) {
temp = temp->next;
i--;
}
return temp->data;
}
throw std::out_of_range("Index out of range");
};
// const T &operator[](size_type i) const; //how to implement and do not duplicate code?
Node *push_back(value_type data) {
Node *n = new Node(data);
if (head == NULL) {
head = tail = n;
} else {
n->previous = tail;
tail->next = n;
tail = n;
}
return n;
};
Node *push_front(value_type data) {
Node *n = new Node(data);
if (head == NULL) {
head = tail = n;
} else {
n->next = head;
head->previous = n;
head = n;
}
return n;
};
void pop_front() {
remove(head);
};
void pop_back() {
remove(tail);
};
void remove(Node *n){
if(n == NULL) return;
if(n == head){
head = n->next;
head->previous =NULL;
}
else if(n == tail){
tail = n->previous;
tail->next = NULL;
}
else{
n->previous->next = n->next;
n->next->previous = n->previous;
}
delete n;
}
};
这是main.cpp
#include <iostream>
#include "List.h"
int main(){
List<int> l;
l.push_back(1);
l.push_back(2);
l.push_back(3);
l.pop_back();
l.pop_front();
l.push_back(4);
l.push_back(5);
for (size_t i = 0; i < l.size(); i++)
std::cout << l[i] << "\n";
std::cout<<"Front "<<l.front();
std::cout<<"Back "<<l.back();
}
实际上push_back / front,pop_back / front和[]运算符工作正常。但我得到“流程完成退出代码139” 我尝试使用front()或back()时出错。我知道列表模板的这个迭代器不起作用,但我知道如何将它组合起来。有人可以暗示或帮忙吗?
编辑: 好的,我已经修复了删除和front(),tail()方法的问题。但仍然是迭代器的东西不起作用。 例如这段代码:
for(List<int>::iterator it = l.begin(); it!=l.end(); it++){
std::cout << it << "\n";
}
给我错误:
error: cannot convert ‘List<int>::Node*’ to ‘List<int>::iterator {aka int*}’ in initialization
for(List<int>::iterator it = l.begin(); it!=l.end(); it++){
^
error: comparison between distinct pointer types ‘List<int>::iterator {aka int*}’ and ‘List<int>::Node*’ lacks a cast [-fpermissive]
for(List<int>::iterator it = l.begin(); it!=l.end(); it++){
^
我知道问题在于使用迭代器模板包装节点,并且我有“typename T * iterator”。
答案 0 :(得分:3)
您的begin
和end
方法返回Node*
,而不是您的迭代器类型。并且您创建了接受Node*
作为参数explicit
的迭代器构造函数;你告诉编译器禁止从List<int>::Node*
到List<int>::iterator
的隐式转换。
您必须执行以下操作之一:
explicit
移除explicit iterator(Node *n) : underlying(n) { };
(虽然这可能会在您不想要的情况下隐含转化)begin
和end
以返回iterator(head)
和iterator(tail)
(执行显式转换为iterator
)而不是head
和{{1 (并将tail
和begin
的返回类型更改为end
,无论如何都应该这样做。您还有其他一些问题:
iterator
中完成typedef T* iterator
;隐藏了List
类的定义,因此iterator
从未使用它。修复(并为List
的使用添加必要的模板)使其编译iterator
的继承定义应为iterator
而不是template<typename T, class Node> class iterator : public std::iterator<std::bidirectional_iterator_tag, T>
;后者声明解除引用的值应为template<typename T, class Node> class iterator : public std::iterator<std::bidirectional_iterator_tag, Node *, Node &>
(当您希望它为Node *
时,每个T
中的值)Node
应该返回end
而不是iterator<T, Node>(nullptr)
;否则,如果要在终止循环之前打印iterator(tail)
,则在打印tail
的值之前停止。完成所有这些后,您应该编译并获得您期望的结果。代码仍有问题,例如
tail
正确的,并且不提供各种访问者的const
版本,这可能会阻止优化;如果编译器无法确定循环实际非变异const
size
不起作用(您想要反复迭代create
和rhs
,您不能使用push_back
推送新值iterator
访问者意味着不能使效用函数起作用;它需要一个const
迭代器类型来迭代const
,并保证它不会违反rhs
要求,但你只定义了变异迭代器函数但是,你的代码中的性能优化和正确性是你没有运用的;一旦您对新代码感到满意,就可以解决这个问题。
我your code(虽然复制构造/分配的修复程序是使用const List&
围绕缺少const_cast
安全迭代的暴力破解的恶劣攻击);我还添加了几个测试来显示复制构造和分配工作。 Take a look
答案 1 :(得分:1)
问题(问题?)在remove()
:您不检查head
是NULL
(head
案例),如果{{1} {}} tail
NULL
{}} tail
和n->previous
为空(通用案例)
我建议n->next
remove()