簡體   English   中英

C 鏈表的 C++ 迭代器:使用基於范圍的 for 循環

[英]C++ Iterator for C Linked Lists: to use range-based for loops

我正在使用舊的C代碼,新代碼是用C++編寫的。 為了使用 C++ 標准庫,我在閱讀了 Bjarne Stroustrup 關於Adaptation的博文后,為舊版LinkedList編寫了一個簡單的Iterator ,如下所示。

我的問題是:

  1. 我想為另一個struct創建另一個Iterator ,比如struct TokenList 我不確定如何使用namespace並且仍然能夠使用基於范圍的for循環。 任何指針都會有所幫助。

  2. Iterator的適配器,即: beginend++*!=正確嗎? 目前,我對使用基於范圍的for循環讀取LinkedList的內容很感興趣。

科利魯

#include <cstdio>
#include <numeric>
#include <algorithm>

struct LinkedList {
    double v;
    LinkedList *next;
};

struct Iterator {
    LinkedList *current;
    LinkedList &c;
};

Iterator begin(LinkedList *c) { return Iterator {c, *c}; }
Iterator end(LinkedList *c) { return Iterator {nullptr, *c}; }
Iterator &operator++(Iterator &p) { p.current = p.current->next; return p; }
LinkedList *operator*(Iterator p) { return p.current; }
bool operator!=(Iterator lhs, Iterator rhs) { return (lhs.current != rhs.current); }

int main()
{
    LinkedList *node1 = new LinkedList;
    LinkedList *node2 = new LinkedList;
    LinkedList *node3 = new LinkedList;

    node1->v = 1; node1->next = node2;
    node2->v = 2; node2->next = node3;
    node3->v = 3; node3->next = nullptr;

    printf("// C style: iteration\n");
    for (auto ptr = node1; ptr; ptr = ptr->next) {
        printf("%e\n", ptr->v);
    }

    auto head = node1;
    // make use of begin(), end(), ++, != and *
    printf("// Modern C++ style: range based for-loop\n");
    for (const auto& it : head) {
        printf("%e\n", it->v);
    }

    std::for_each(begin(head), end(head), [](auto t) { delete t; });

    return 0;
}

迭代器是偽指針類型。 這意味着他們自己是有規律的。

struct Iterator {
  LinkedList *current;
  LinkedList &c;
};

在這里你混合引用和指針。 這是一個嚴重的反模式,賦值是做什么的? 沒有明智的答案。

我會完全刪除c成員。

接下來你需要廣播一個迭代器類型。 你的看起來像一個前向迭代器。 所有結束迭代器都可以相等。

Iterator begin(LinkedList *c) { return Iterator {c, *c}; }
Iterator end(LinkedList *c) { return Iterator {nullptr, *c}; }

這些看起來不錯。

請注意,名稱不必是Iterator begin / end必須在LinkedList的命名空間中定義,但返回類型不必是。

Iterator &operator++(Iterator &p) { p.current = p.current->next; return p; }

我通常將其實現為成員 function,並實現前后遞增; post 是使用 pre 和 copy 實現的。

LinkedList *operator*(Iterator p) { return p.current; }

這是錯誤的。 它應該返回*p.current作為double&

bool operator!=(Iterator lhs, Iterator rhs) { return (lhs.current != rhs.current); }

當然。 還將==實現為!(lhs!=rhs)

查找前向迭代器概念和前向迭代器標簽。 包括std::iterator_traits所需的類型。

對於其他要迭代的東西,給迭代器一個不同的名字。 這可以通過不同的命名空間。

如果不同的只是值的類型,你可以很容易地把它變成一個模板。 然后你只需要手動編寫begin / end

如果v的名稱也發生變化,您可以在作為自定義點編寫的GetValue(List*) function 上使用 ADL。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM