简体   繁体   English

外部双链表迭代器c ++

[英]External Doubly Linked-list Iterator c++

I made a doubly linked list. 我做了一个双向链表。 In my main, I need to use an external List Iterator that has a constructor that takes a list. 在我的主体中,我需要使用一个外部List Iterator,它具有一个接受列表的构造函数。 This is what I have so far: 这是我到目前为止的内容:

struct ListIterator : List {
    Node* cur = head;

    ListIterator(List* list) {
        this -> list = list;
    }

    bool hasNext() {
        return (cur -> next) != nullptr;
    }

    int next() {
        return list.at(cur -> next);
    }
};

This is my main: 这是我的主要:

List list1;

list1.append('I');
list1.append('D');
list1.append('F');
list1.append('G');
ListIterator it(list1);

while (it.hasNext()) {
   cout << it.next();
}

As you can see, I'm trying to use hasNext() and next() to display all the nodes in a list. 如您所见,我正在尝试使用hasNext()和next()来显示列表中的所有节点。 I'm confused on how to create a constructor that takes a list and use the function in ListIterator struct. 我对如何创建一个接受列表并在ListIterator struct中使用该函数的构造方法感到困惑。 Any tips and hints would be very much appreciated. 任何提示和暗示将不胜感激。

You seem to be heavily influenced by Java (or perhaps even C#). 您似乎深受Java(甚至C#)的影响。 It's not a bad thing, you just need to learn the ins and outs of C++. 这不是一件坏事,您只需要学习C ++的来龙去脉。

For your first problem: in C++, there is a clear distinction between values, references and pointers. 第一个问题是:在C ++中,值,引用和指针之间有明显的区别。 When you declare an instance of your List class as follows: 当您声明List类的实例时,如下所示:

List list1;

that is actually a value. 这实际上是一个价值。 The instance exists on the stack and will be properly disposed off (the destructor will be called) once the scope is ended. 该实例存在于堆栈中,并且在范围结束时将被适当地处置(将调用析构函数)。

If you now were to initialize a second list as follows: 如果现在要初始化第二个列表,如下所示:

List list2 = list1;

that is also a value, and it will copy the entire list (the copy constructor or assignment operator will be called). 这也是一个值,它将复制整个列表(将调用复制构造函数或赋值运算符)。 Now list1 and list2 are two distinct list instances and modifying one will not affect the other. 现在list1list2是两个不同的列表实例,修改一个实例不会影响另一个实例。

Anyhow, to get a pointer to a list, you need the following syntax: 无论如何,要获得指向列表的指针,您需要以下语法:

List *listPtr1 = &list1;

As it is a pointer, an indirection, copying it will not copy the underlying structure: 由于它是一个指针,因此进行间接复制将不会复制基础结构:

List *listPtr2 = listPtr1; // Will also point to list1

While using the proper syntax will solve your immediate problem, it doesn't properly address the odd iterator implementation. 虽然使用正确的语法可以解决您的直接问题,但不能正确解决奇数迭代器的实现。

In C++, iterators either point to a single element in a container or they point past-the-end . 在C ++中,迭代器要么指向容器中的单个元素,要么指向过去 An iterator typically does not know if the end of the container is reached by itself; 迭代器通常不知道容器自身是否到达了容器的末端。 instead, it needs to be compared to this past-the-end iterator. 相反,需要将其与该过去的迭代器进行比较。

Containers typically define a begin method that returns an iterator to the first element, and an end method that returns an iterator to past-the-end . 容器通常定义一个begin方法,该方法将迭代器返回到第一个元素,一个end方法,将迭代器返回给past-the-end

Iterating over a container typically happens using the following prototype: 通常使用以下原型在容器上进行迭代:

for (auto it = container.begin(); it != container.end(); ++it)
{
    // To access the element, you need to dereference the iterator:
    std::cout << "The current value is :" << *it << std::endl;
}

In this regard, iterators behave much like pointers to the elements. 在这方面,迭代器的行为非常类似于指向元素的指针。 There's no need for the clunky next and hasNext methods. 不需要笨拙的nexthasNext方法。 You simply get an iterator to the start of your container, make sure to stop iterating once it points to past-the-end , and increment it when you want to go to the next element. 您只需将迭代器添加到容器的开头,请确保一旦它指向past-the-end ,就停止迭代,并在要转到下一个元素时将其递增。

A container that properly defines the begin and end methods can also be used in a range-based for loop : 正确定义beginend方法的容器也可以在基于范围的for循环中使用

for (auto &element : container)
{
    std::cout << "The current value is :" << element << std::endl;
}

I understand it is fun and very educational to implement your own containers. 我知道实现自己的容器很有趣而且很有教育意义。 I reinvented my fair share of wheels just to understand how things work exactly, so nothing wrong with that. 我重新发明了相当多的轮子,只是为了了解事情是如何工作的,所以这没有错。 But I would advice you to perhaps play around with standard C++ containers first, get the hang of the major differences between C++ and languages like Java and C# and then have another go at the exercise. 但是我建议您也许首先使用标准C ++容器,掌握C ++与Java和C#等语言之间的主要区别,然后再进行练习。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM