【问题标题】:implementing a cpp const iterator crashes and burns实现 cpp const 迭代器崩溃和烧毁
【发布时间】:2021-12-30 06:39:17
【问题描述】:

许多关于 const 迭代器 (example) 的帖子,但没有关于循环上下文的帖子,例如:

for (const auto it: container) { ... }

当我开始实施时,鼓励编译器抱怨缺少beginend,希望这些抱怨能够指导我填写在丢失的部分。我错了。以下代码编译得很好,尽管它肯定缺少 operator++operator!= 的等效项:

#include <iostream>
template<class T> class List { public:
    const T *head;
    const List<T> *tail;
    List(const T *h, const List<T> *t):head(h),tail(t){}
    const T *operator*() const { return head; } };

template<class T> const List<T> *begin(const List<T> *l) { return l; }
template<class T> const List<T> *end  (const List<T> *l) { return nullptr; }

class Person { public: int age; Person(int a):age(a){} };
typedef List<Person> Persons;

int main(int argc, char **argv) {
    Person *p1 = new Person(16);
    Person *p2 = new Person(27);
    Person *p3 = new Person(38);

    Persons *persons = new Persons(p1,
        new Persons(p2,
        new Persons(p3, nullptr)));

    for (const auto p: persons) { std::cout << (*p)->age << "\n"; }
    return 0; }

这段代码是怎么编译的?

【问题讨论】:

  • 这里没有迭代器。而 range for 循环只是普通 for 循环的简写语法
  • ++!= 是为所有指针类型定义的
  • 我不明白为什么persons,一个Persons* 指针,被视为一个有效的范围表达式。唯一看起来可以应用的case 是将其视为大小未知的数组类型。
  • 这是因为定义了 begin() 和 end() 函数,它们接受 List* 作为参数。

标签: c++ iterator


【解决方案1】:

您还没有定义++!=,但是对于您的迭代器类型const List&lt;T&gt;*,它们是完美定义的,因为它是一个指针类型。但是,++ 的默认行为并没有按照您的意愿行事,即跟随 tail 指针。

要让您的迭代器了解如何实现 ++ 的特殊知识,您需要使用单独的自定义迭代器类,而不是使用指针。

我还对您的代码进行了一些其他更改:

  • List 类型是可迭代的,而不是 List*。这意味着 beginend 函数不是在指针上定义的,而是在 List 对象本身上定义的,我们迭代 *persons 而不是 persons
  • for (const auto p : *persons) 中,pPerson,而不是指针。

godbolt.org link

#include <iostream>
template<class T> class List { public:
    const T *head;
    const List<T> *tail;
    List(const T *h, const List<T> *t):head(h),tail(t){}
    const T *operator*() const { return head; }

    class const_iterator {
        const List<T>* cur = nullptr;
    public:
        explicit const_iterator(const List<T>* list) : cur(list) {}
        const_iterator& operator++() {
            cur = cur->tail;
            return *this;
        }
        bool operator!=(const const_iterator& other) const {
            return cur != other.cur;
        }
        const T& operator*() const {
            return *cur->head;
        }
    };

    const_iterator begin() const {
        return const_iterator(this);
    }

    const_iterator end() const {
        return const_iterator(nullptr);
    }
};

class Person { public: int age; Person(int a):age(a){} };
typedef List<Person> Persons;

int main(int argc, char **argv) {
    Person *p1 = new Person(16);
    Person *p2 = new Person(27);
    Person *p3 = new Person(38);

    Persons *persons = new Persons(p1,
        new Persons(p2,
        new Persons(p3, nullptr)));

    for (const auto p: *persons) {
        std::cout << p.age << "\n";
    }
    return 0;
} 

【讨论】:

    猜你喜欢
    • 2020-10-02
    • 1970-01-01
    • 2011-01-10
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    相关资源
    最近更新 更多