开发者

C++ Set Iterator in Class

I have a class, which has a member named _Emails. It is of the type 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. I initialize it in my constructor, right after my _Emails, like so:

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

T开发者_JS百科hen, attempting to do a similar for loop:

// 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()). 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?)


When you first create the set _Emails, and then set _EmailItr to _Emails->begin(), the iterator is not pointing to anything. In fact, it is pointing to _Emails->end(), since when the set is empty, begin() and end() are the same.

So later, you attempt to dereference an iterator which points to end(), which is undefined behavior and leads to your crash.

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(). You need to set it to _Emails->begin() after you insert elements into the set.


Also, unrelated to your question, but: is there some reason you need to allocate _Emails on the heap?


The STL set is well-behaved when inserting new elements during an iteration. In particular, if you're iterating over a set while adding new elements, you won't "lose track" of where you are; 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜