加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – C自定义迭代器?

发布时间:2020-12-16 06:50:01 所属栏目:百科 来源:网络整理
导读:我一直在尝试为一个简单的类实现一个自定义前向迭代器.这个类对于固定数组来说是一个非常糟糕的抽象(不幸的是我不能改变它).只能使用索引访问元素. template class Tstruct data{ static const size_t MAX_BUFFER{ 50 }; T* buffer_[MAX_BUFFER] = {}; int c
我一直在尝试为一个简单的类实现一个自定义前向迭代器.这个类对于固定数组来说是一个非常糟糕的抽象(不幸的是我不能改变它).只能使用索引访问元素.

template <class T>
struct data
{
    static const size_t MAX_BUFFER{ 50 };
    T* buffer_[MAX_BUFFER] = {};
    int currpos_ = 0;

    void insert(T *value) {
        if (currpos_ < MAX_BUFFER-1)
            buffer_[currpos_++] = value;
    }

    T** at(int i) {
        if (i >= currpos_)
            return NULL;
        return &buffer_[i];
    }

    ~data() {
        for (int i=0; i<currpos_; ++i)
            delete buffer_[i];
    }

    int entries() const { return currpos_; }

    struct iterator : std::iterator<std::forward_iterator_tag,T*>
    {
        using reference = typename std::iterator<std::forward_iterator_tag,T*>::reference;
        using pointer = typename std::iterator<std::forward_iterator_tag,T*>::pointer;

        iterator(data<T> *d,int start) : p{ d },index{ start } {}
        iterator operator++() { if (index < p->entries()) ++index; return *this; }
        friend bool operator==(const iterator &d1,const iterator &d2) { return d1.p == d2.p && d1.index == d2.index; }
        friend bool operator!=(const iterator &d1,const iterator &d2) { return !(d1== d2); }
        reference operator*() { return *(p->at(index)); }
        pointer operator->() { return p->at(index); }
        data<T> *p;
        int index;
    };

    iterator begin() { return iterator(this,0); }
    iterator end() { return iterator(this,entries()); }
};

我面临的问题是,通过这个界面,我可以使用大多数STL标准算法,如for_each,transform,find_if.例如,假设已使用新{2},新{3},新{4},新{14},新{-4},新{-44},新{42}此代码初始化了d

for (auto &i : d) std::cout <<*i <<" "; std::cout <<std::endl;

auto res=std::find_if(d.begin(),d.end(),[](auto &i) { return *i == -44;});
if (res != d.end())
    std::cout <<**res <<std::endl;

std::transform(d.begin(),d.begin(),[](auto &i) {*i *= 2; return i;});
for (auto &i : d) std::cout <<*i <<" "; std::cout <<std::endl;

会正确显示

2 3 4 14 -4 -44 42
-44
4 6 8 28 -8 -88 84

我面临的问题是算法std :: remove_if()以及它排列元素的方式.我添加了一个类似于vector :: erase的成员函数:

void remove_range(iterator begin,iterator end)
{
    size_t d=std::distance(begin,end);
    currpos_ -= d;
}

当然还应该删除与已删除元素关联的内存.在这个示例中调用它时:

auto new_end = std::remove_if(d.begin(),[](auto &r) { return *r > 3; });
d.remove_range(new_end,d.end());

valdring一直告诉我,我有3个内存泄漏(这是有道理的:有3个元素> = 3).我试图在remove_range()中添加删除操作,但是这个解决方案不起作用(程序崩溃).在调试会话期间,我打印出d的内部状态:

(gdb) p d
$1 = {static MAX_BUFFER = <optimized out>,buffer_ = {0x603010,0x603030,0x603050,0x603070,0x603090,0x6030b0,0x6030d0,0x0 <repeats 43 times>},currpos_ = 7}
(gdb) p d
$2 = {static MAX_BUFFER = <optimized out>,currpos_ = 7}

我可以看到removed_if()基本上移动了三个元素(那些> 3)并且我认为我泄漏的原因是因为要删除的元素被移动所以原始指针永远泄露.

我的问题是:有没有办法避免这种泄漏?我是否需要定义一些额外的移动构造函数?

解决方法

您看到的泄漏是由remove_range实现引起的,而不是迭代器引起的.

I have added a member function similar to vector::erase …
which of course should also remove the memory associated to the deleted elements.

但事实并非如此.您在容器析构函数中调用元素的删除,但擦除方法中的项目没有删除.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读