在 C++ 中为我自己的自定义向量模板类实现迭代器(类似于 STL)[重复]

Posted

技术标签:

【中文标题】在 C++ 中为我自己的自定义向量模板类实现迭代器(类似于 STL)[重复]【英文标题】:implementing an iterator (something like from STL) for my own custom vector template class in C++ [duplicate] 【发布时间】:2021-07-01 14:46:37 【问题描述】:

我有一个来自 GeeksforGeeks 网站的自己的容器,我从下面的容器代码中获得。我喜欢创建一个迭代器类,它的功能将使我能够使用for 循环和函数,例如在我的容器中开始和结束,而 for 循环将类似于

MyClassForIterator iter;
for(iter=mycontainer_items_obj.begin();iter!=mycontainer_items_obj.end();iter++)

cout<<*iter<<endl
...

我想知道这在 C++ 中是否可行以及如何实现?

矢量模板类

#include <bits/stdc++.h>
using namespace std;
template <typename T> class vectorClass


    // arr is the integer pointer
    // which stores the address of our vector
    T* arr;

    // capacity is the total storage
    // capacity of the vector
    int capacity;

    // current is the number of elements
    // currently present in the vector
    int current;

public:
    // Default constructor to initialise
    // an initial capacity of 1 element and
    // allocating storage using dynamic allocation
    vectorClass()
    
        arr = new T[1];
        capacity = 1;
        current = 0;
    

    // Function to add an element at the last
    void push(T data)
    

        // if the number of elements is equal to the
        // capacity, that means we don't have space to
        // accommodate more elements. We need to double the
        // capacity
        if (current == capacity) 
            T* temp = new T[2 * capacity];

            // copying old array elements to new array
            for (int i = 0; i < capacity; i++) 
                temp[i] = arr[i];
            

            // deleting previous array
            delete[] arr;
            capacity *= 2;
            arr = temp;
        

        // Inserting data
        arr[current] = data;
        current++;
    

    // function to add element at any index
    void push(int data, int index)
    

        // if index is equal to capacity then this
        // function is same as push defined above
        if (index == capacity)
            push(data);
        else
            arr[index] = data;
    

    // function to extract element at any index
    T get(int index)
    

        // if index is within the range
        if (index < current)
            return arr[index];
    

    // function to delete last element
    void pop()  current--; 

    // function to get size of the vector
    int size()  return current; 

    // function to get capacity of the vector
    int getcapacity()  return capacity; 

    // function to print array elements
    void print()
    
        for (int i = 0; i < current; i++) 
            cout << arr[i] << " ";
        
        cout << endl;
    
;

// Driver code
int main()

    vectorClass<int> v;
    vectorClass<char> v1;
    v.push(10);
    v.push(20);
    v.push(30);
    v.push(40);
    v.push(50);
    v1.push(71);
    v1.push(72);
    v1.push(73);
    v1.push(74);

    cout << "Vector size : " << v.size() << endl;
    cout << "Vector capacity : " << v.getcapacity() << endl;

    cout << "Vector elements : ";
    v.print();

    v.push(100, 1);

    cout << "\nAfter updating 1st index" << endl;

    cout << "Vector elements of type int : " << endl;
    v.print();
    // This was possible because we used templates
    cout << "Vector elements of type char : " << endl;
    v1.print();
    cout << "Element at 1st index of type int: " << v.get(1)
        << endl;
    cout << "Element at 1st index of type char: "
        << v1.get(1) << endl;

    v.pop();
    v1.pop();

    cout << "\nAfter deleting last element" << endl;

    cout << "Vector size of type int: " << v.size() << endl;
    cout << "Vector size of type char: " << v1.size()
        << endl;
    cout << "Vector capacity of type int : "
        << v.getcapacity() << endl;
    cout << "Vector capacity of type char : "
        << v1.getcapacity() << endl;

    cout << "Vector elements of type int: ";
    v.print();
    cout << "Vector elements of type char: ";
    v1.print();

    return 0;

【问题讨论】:

当然可以在 C++ 中使用,但这是一个相当高级、复杂的主题,需要编写大量代码。不幸的是,您不太可能从某些网站或 Youtube 视频中学习这些高级、复杂的 C++ 主题。学习高级 C++ 主题的唯一现实方法是with an advanced C++ textbook。 容器已损坏,因为它没有遵循rule of 3/5。不幸的是,在您找到它的网站上找到相当糟糕的代码并不罕见。标题应该是“如何在 C++ 中实现我们自己完全损坏的向量类?”而不是在最后加上免责声明“注意读者!现在不要停止学习。”免责声明应该在开头说“注意读者!接下来是如何不实现容器”。我不喜欢咆哮,但我不想让你被愚弄 【参考方案1】:

是的,在 C++ 中完全可以在你的向量中定义一个嵌套的迭代器类。在这里,我定义了一个前向迭代器,对于您的情况,您可能想要选择不同的类别:

template <typename T> class vectorClass

    T* arr;
    int capacity;
    int current;

public:
    struct iterator 
     
        // You need these tags to provide introspection and conform
        // to standard implementations of iterators. If you were 
        // using Boost to define your iterator, you'd define those in
        // the base class.
        using iterator_category = std::forward_iterator_tag;
        using difference_type   = std::ptrdiff_t;
        using value_type        = T;
        using pointer           = value_type*;
        using reference         = value_type&;

        iterator(pointer ptr) : m_ptr(ptr) 

        reference operator*() const  return *m_ptr; 
        pointer operator->()  return m_ptr; 

        // Prefix increment
        iterator& operator++()  m_ptr++; return *this;   

        // Postfix increment
        iterator operator++(int) 
         Iterator tmp = *this; ++(*this); return tmp; 

        friend bool operator== (const Iterator& a, const Iterator& b) 
         return a.m_ptr == b.m_ptr; ;
        friend bool operator!= (const Iterator& a, const Iterator& b) 
         return a.m_ptr != b.m_ptr; ;

    private:
        pointer m_ptr;
    ;

    // Add begin/end functions to your class
    iterator begin()  return iterator(arr); 
    iterator end()    return iterator(arr + curr); 

    /* 
    REST of the class remains the same 
    */
;

您可能已经在 cmets 中注意到,我提到了 boost iterator facade library 作为定义迭代器的工具。如果这是您的选择,您可以使用它来消除大部分样板文件。

【讨论】:

如果我在迭代器结构构造函数中尝试pointer ptr等,您能否添加我需要添加的头文件? @user786 我想你只需要 #include &lt;iterator&gt; 。您是否从代码中得到错误? 不,我还没有编译它。但我很快就会去做。感谢您的评论 这个类也可以使用push_back函数吗 @user786 当然,迭代器实现只需要你保持arrcurr成员的顺序。所以现有的push(如问题中所写)有效。【参考方案2】:

如果您的容器在内部将其数据存储为 contiguios 数组(就像您的那样),那么您可以简单地使用 pointer 作为迭代器:

template <typename T> class vectorClass

public:
    T* begin()  return arr; 
    T* end()  return arr + current; 

    T const* begin() const  return arr; 
    T const* end() const  return arr + current; 

    // ... etc...
;

这是因为 pointer 满足 iterator 的所有要求。事实上,迭代器是指针的泛化

【讨论】:

以上是关于在 C++ 中为我自己的自定义向量模板类实现迭代器(类似于 STL)[重复]的主要内容,如果未能解决你的问题,请参考以下文章

c++迭代器在迭代向量时崩溃

类元素加入的 C++ 自动迭代器向量

初识STL

vector<struct> 的自定义迭代器

c++模板和迭代器

typedef和模板的未定义符号? [复制]