-4

I am working on some C++ program right now and cannot resolve the above question. I see in forms this has been asked before, but neither answer was satisfying to me.

So, I am working with containers (e.g. a list), additionally I have an array with iterators to this list. I have been doing the following: Initially, I set all iterators in the array as pointing to a dummy list (DummyList.begin()). To check, if the iterator was initialized I used to check (it != DummyList.begin()), in case needed I would then set the iterator to some element of the real list.

This seems to work. However, when trying this for other contains (i.e. boost::circular_buffer), I got invalid iterator errors, and upon googling I found e.g. this comparing iterators from different containers, which says that comparing iterators from different containers produces undefined behavior. That would be scary. Is this still the case? If yes, then why did my program work so far? And how would I do this otherwise then?

Edit: The code looks something like this: Initialization:

std::list<int> DummyList; 
M = new std::list<int>::iterator[n + 1];
for (int i=0;i<=n;++i) {
   M[i] = DummyList.begin();
}

Later than the check:

if (M[i] == DummyList.begin())
   ....
Community
  • 1
  • 1
Oliver
  • 118
  • 11
  • 3
    Show us your code! Why writing a story here? – CinCout Nov 27 '15 at 13:02
  • "Why did my program work so far?" Because Undefined Behaviour is undefined. "Appearing to work" is a valid form of UB (and usually the worst one). – Angew is no longer proud of SO Nov 27 '15 at 13:03
  • Seriously, folks, what's to downvote here? This question does not *need* code to be answerable, it makes sense as is. – Angew is no longer proud of SO Nov 27 '15 at 13:09
  • Yes, I also thought of a general question with simple code, but thanks and sorry, added a piece! – Oliver Nov 27 '15 at 13:09
  • 1
    Note that undefined behavior means that it can behave in **any** way, this includes it may behave in the way you wish it to behave (but then by some arbitrary event it can alter to behave in radically different way). This one of the dangers of UB - it "appears to work" only to make nasal demons fly out of your nose when installed on your clients computer. – skyking Nov 27 '15 at 13:14
  • Alright thank you guys! See my answer below. That's what I feared / expected ... but still the program not only runs without errors but also the results are correct .. i.e. the checks return true and false in the right moments etc., ... very strange. So I thought I could use it ... – Oliver Nov 27 '15 at 13:16
  • One solution to the problem is to wrap the iterator together with a reference to the container it belongs to. Then you can always first check if the container is the correct one before comparing the actual iterator. – skyking Nov 27 '15 at 13:18
  • Iterators are not meant for long-term storage, they're meant for iteration (hence the name). In general, you should consider them as transient data. The syntax looks like pointer syntax in order to enable generic algorithms, but the similarities end there. – molbdnilo Nov 27 '15 at 13:34
  • Makes sense. What is the "right" method to store references to objects in a container then though? To me iterators seemed natural. – Oliver Nov 27 '15 at 13:52

1 Answers1

0

Yes, iterators can only be compared if they belong to the same container. Otherwise, the result is Undefined. Note that "appearing to work" is a valid form of Undefined Behaviour (and usually the worst one, as it hides errors).

What you can do in your case is use something like boost::optional to only store valid iterators in your array:

std::array<boost::optional<MyList::iterator>>, 10> iterators;

if (!iterators[i]) // iterator is not initialised
  iterators[i] = myList.begin(); // store valid iterator
else
{
  MyList::iterator it = *iterators[i]; // access valid iterator
  iterators[i] = boost::none; // make iterator in array invalid again
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Alright thank you, that's what I feared ... still the program not only runs without errors but also the results are correct .. i.e. the checks return true and false in the right moments etc., that's why I wondered ... very strange. So I thought I could use it ... – Oliver Nov 27 '15 at 13:11
  • But thanks, boost::optional seems well suited. How can I change the value at some point to undefined again though? I need that too. – Oliver Nov 27 '15 at 13:21
  • @Oliver Added to answer. – Angew is no longer proud of SO Nov 27 '15 at 13:23