简体   繁体   English

C ++在类中设置迭代器

[英]C++ Set Iterator in Class

I have a class, which has a member named _Emails. 我有一堂课,有一个名为_Emails的成员。 It is of the type set<PEmail*> . 类型为set<PEmail*> When I'm in a member function, and run the following code, it works as expected: 当我处于成员函数中并运行以下代码时,它会按预期工作:

for( set<PEmail*>::iterator it=this->_Emails->begin(); it!=this->_Emails->end(); ++it )
  { 
    cout << "Email: " << (*it)->getEmail() << endl;
  }

That is, it yields a list of email addresses. 也就是说,它会生成电子邮件地址列表。 Now, I'd like to be able to add to this set as the class grows, and not lose my place of last iteration. 现在,我希望能够随着类的增长而添加到该集合中,而又不会失去上一次迭代的位置。 I attempted to make another member of my class, named _EmailItr, of type set<PEmail*>::iterator . 我试图让我的班级的另一个成员_EmailItr成为set<PEmail*>::iterator I initialize it in my constructor, right after my _Emails, like so: 我在_Emails之后立即在构造函数中对其进行初始化,如下所示:

this->_Emails = new set<PEmail*>;
this->_EmailItr = this->_Emails->begin();

Then, attempting to do a similar for loop: 然后,尝试执行类似的for循环:

// send the max queue amount, or until there are no more emails                                         
for( int i=0;  i<this->_QueueSize || i==_Emails->size(); ++i )
  {
    cout << "i: " << i << endl;
    cout << "QueueSize: " << this->_QueueSize << endl;
    cout << "Emails: " << this->_Emails->size() << endl;

    cout << (*_EmailItr)->getEmail() << endl;
  }

I get the following output: 我得到以下输出:

i: 0
QueueSize: 2
Emails: 2
Segmentation fault

What gives? 是什么赋予了? Am I trying to use iterators in an improper way? 我是否试图以不正确的方式使用迭代器?

When you get this->_Emails->begin() right after creating the std::map , the iterator you get is the end iterator (because there are no elements in the std::map , its size is zero and begin() == end() ). 在创建std::map之后this->_Emails->begin()获得this->_Emails->begin() ,您得到的迭代器是结束迭代器(因为std::map中没有元素,其大小为零, begin() == end() )。 You cannot dereference or increment an end iterator. 您不能取消引用或增加最终迭代器。 It doesn't point to "the beginning of the container;" 它并不指向“容器的开始”; it points to "the element currently at the beginning" or if the container is empty, it returns the end iterator. 它指向“当前在开头的元素”,或者如果容器为空,则返回结束迭代器。

(On an unrelated note, it looks like you are doing way too much dynamic allocation. Why are you creating the std::set object dynamically (using new )? Why not just have a std::set as a member of the class?) (在一个不相关的注释上,您似乎在进行过多的动态分配。为什么要动态创建std::set对象(使用new ?)?为什么不只是将std::set作为类的成员呢? )

When you first create the set _Emails , and then set _EmailItr to _Emails->begin() , the iterator is not pointing to anything. 当您首先创建_Emails集,然后将_EmailItr设置为_Emails->begin() ,迭代器没有指向任何对象。 In fact, it is pointing to _Emails->end() , since when the set is empty, begin() and end() are the same. 实际上,它指向_Emails->end() ,因为当集合为空时, begin()end()相同。

So later, you attempt to dereference an iterator which points to end() , which is undefined behavior and leads to your crash. 因此,稍后,您尝试取消引用指向end()的迭代器,这是未定义的行为,并导致崩溃。

You seem to be assuming that the iterator is actually somehow "updating" behind the scenes as you add new objects to the list. 您似乎在假设迭代器实际上是在向列表中添加新对象时以某种方式在后台“更新”。 It's not. 不是。 It's always pointing to end() . 它总是指向end() You need to set it to _Emails->begin() after you insert elements into the set. 将元素插入集合后,需要将其设置为_Emails->begin()


Also, unrelated to your question, but: is there some reason you need to allocate _Emails on the heap? 另外,与您的问题无关,但是:是否有某些原因需要在堆上分配_Emails

The STL set is well-behaved when inserting new elements during an iteration. 在迭代期间插入新元素时,STL set表现良好。 In particular, if you're iterating over a set while adding new elements, you won't "lose track" of where you are; 特别是,如果要在添加新元素的同时迭代set ,则不会“遗失”您所在的位置; your iterator will remain valid and it will see any new elements that were added or removed. 您的迭代器将保持有效,并且将看到添加或删除的所有新元素。 I'm not fully sure what your use case is here, but I don't think you need all of the added machinery you've introduced here. 我不确定您的用例在哪里,但我认为您不需要在这里介绍的所有新增设备。 Just using a good old-fashioned iterator without any adornments should work just fine. 只使用一个没有任何装饰的老式迭代器就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM