【问题标题】:Iterator gives different results based on usage c++迭代器根据用法 c++ 给出不同的结果
【发布时间】:2019-05-22 09:22:18
【问题描述】:

我最近开始了 C++ 编程。我从 Java 转移。 我正在构建自己的 Iterable 类模板,如下所示:

template<class T> class Iterable
    {
        T start,stop;
    public:
        explicit Iterable(T s,T e) {start=s; stop=e;;}


    public:
        virtual void next(T& i) =0;
    public:
        class iterator: public std::iterator<
        std::input_iterator_tag,   // iterator_category
        T,                      // value_type
        long,                      // difference_type
        const T*,               // pointer
        T                       // reference
        >{
            T current;
            Iterable<T>* obj;
        public:
            explicit iterator(T t,Iterable<T>* o) : obj(o) {current=t;}
            iterator& operator++() {obj->next(current); return *this;}
            iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
            bool operator==(iterator other) const {return current == other.current;}
            bool operator!=(iterator other) const {return !(*this == other);}
            const T& operator*() const {return current;}
        };
        iterator begin() {return iterator(start,this);}
        iterator end() {return iterator(stop,this);}
    };

当我尝试使用这个迭代器时,如果调用方式不同,我会得到不同的结果:

for(auto S=SI.begin();S!=SI.end();S++)
    {
        cout << *S << "\n";
        //cout << contains(seqs,S) << "\n";
        if(!contains(seqs,*S))
            seqs.push_back(*(new Sequence(*S)));
    }

给出了不同的结果:

for(Sequence S : SI)
    {
        cout << S << "\n";
        //cout << contains(seqs,S) << "\n";
        if(!contains(seqs,S))
            seqs.push_back(*(new Sequence(S)));
    }

即使在循环中。 我的 SeqIter 类(SI 是这个类的对象)如下:

class SeqIter : public flex::Iterable<Sequence>
{
    int n;
public:
    SeqIter(int s) : Iterable(Sequence(copyList(0,s),s),Sequence(copyList(3,s),s)) {n=s;}

    void next(Sequence& s)
    {
        char ch;
        for(int i=0;i<n;i++)
        {
            ch=nextBase(s[i]);
            s[i]=ch;
            if(ch!=0)
                break;
        }
    }
};

对不起,如果代码太多,但我不知道需要多少代码。


另外,简单解释一下 Sequence 类: 它是一个具有数字数组的类(在这种情况下,我尝试使用 3),它根据第一个序列生成下一个序列,即 000、100、200、300; 010110 ... 每个数字的范围为 0-3(均包含在内) 我无法理解为什么两个循环给出不同的序列(首先给出 000 100 200 300 010 110 而第二个给出 000 100 200 300 000 110) 我认为这两个循环基本上是相同的,第一个只是第二个的扩展。不是这样吗?

也是序列类:(抱歉耽搁了,但我猜这是问题所在)

class Sequence
{
    int size=1;
    char* bps;
public:
    Sequence() {size=0;}
    Sequence(int s) 
    {
        size=s;
        bps=new char[s];
    }
    Sequence(char* arr,int s)
    {
        size=s;
        bps=arr;
    }
    Sequence(const Sequence& seq)
    {
        size=seq.size;
        bps=new char[size];
        strcpy(bps,seq.bps);
    }

    String toString() const {return *(new String(bps,size));}
    inline char* toCharArray() {return bps;}
    inline int getSize() const {return size;}

    //operator overloading
public:
    bool operator==(const Sequence& s2) const
    {
        if(s2.size!=size)
            return false;
        String r1=toString();
        String r2=s2.toString();
        return (r1==r2 || r1==r2.reverse());
    }
    inline bool operator!=(const Sequence& s2) const {return !operator==(s2);}
    const char& operator[](int n) const
    {
        if(n>=size)
            throw commons::IndexOutOfBoundsException(n,size);
        return bps[n];
    }
    char& operator[](int n)
    {
        if(n>=size)
            throw commons::IndexOutOfBoundsException(n,size);
        return bps[n];
    }
    Sequence& operator=(const Sequence& seq)
    {
        size=seq.size;
        bps=new char[size];
        strcpy(bps,seq.bps);
    }
};

【问题讨论】:

  • “但我不知道需要多少代码” minimal reproducible example 是必需的,仅此而已。
  • 我看到三个地方有类似*(new Sequence(*S)) 的代码。那是内存泄漏。您为对象分配内存,取消引用指针以进行复制,然后原始对象被泄露。您的Sequence 类还在几个地方调用new[],但没有析构函数或delete[]。您需要了解资源管理,因为看起来您的代码到处都在泄漏内存。
  • seqs.push_back(*(new Sequence(S))); C++ 不是 Java。您不需要 new 只是为了制作一个对象。你写的是一个多合一的内存泄漏。
  • 这是从 Java 过来的人常犯的一个陷阱。 Java 没有delete,语法与C++ 看似相似,而new 总是用于创建新对象。不幸的是,C++ 不能以这种方式工作。
  • 从 Java 迁移到 C++:(1) 停止使用 new。我的意思是永远不要使用它。在 C++14 及更高版本中,一个完整的程序可以包含 0 个news。创建值,而不是指针。 (2)你对一切的生命负责。 (3) 学习 0/3/5 的规则。学习 RAII。不要将引用放在类或结构中。

标签: c++ for-loop iterator


【解决方案1】:

对不起大家。调试后回答我自己的问题: 在我的 Sequence 类中,我使用 strcpy 复制 char*,其中数组不以 '\0' 结尾 可能是导致错误的原因: 我在网上多看了一下,发现展开是这样的:

for(Sequence S : seqs)
{
...
}

等价于

for(auto i=SI.begin();i!=SI.end();i++)
{
Sequence S=*i;
...
}

所以在作业中,(S=*i) 数据没有被正确复制。 给您添麻烦了

通过删除赋值运算符重载并将复制构造函数更改为:

Sequence(const Sequence& seq)
{
        size=seq.size;
        bps=new char[size];
        for(int i=0;i<size;i++)
            bps[i]=seq[i];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多