tags:

views:

295

answers:

7

Hi,

I am building a DLL that another application would use. I want to store the current state of some data globally in the DLL's memory before returning from the function call so that I could reuse state on the next call to the function.

For doing this, I'm having to save some iterators. I'm using a std::stack to store all other data, but I wasn't sure if I could do that with the iterators also.

Is it safe to put list iterators inside container classes? If not, could you suggest a way to store a pointer to an element in a list so that I can use it later?

I know using a vector to store my data instead of a list would have allowed me to store the subscript and reuse it very easily, but unfortunately I'm having to use only an std::list.

+5  A: 

It should be no problem to store the iterators, just make sure you don't use them on a copy of the list -- an iterator is bound to one instance of the list, and cannot be used on a copy.

That is, if you do:

std::list<int>::iterator it = myList.begin ();
std::list<int> c = myList;

c.insert (it, ...); // Error

As noted by others: Of course, you should also not invalidate the iterator by removing the pointed-to element.

Anteru
Why is it irrevelant? I clearly say it's no problem to store the iterators, and point out that the OP should be careful to not mix and match stored iterators against other container instances.
Anteru
Oh no, Anteru, I wanted to write this to AProgrammer's response. Sorry about that. I've taken it down.
Sahasranaman MS
A: 

The same rule applies to an iterator stored in a local variable as in a longer lived data structure: it will stay valid as long as the container allows.

For a list, this means: as long as the node it points to is not deleted, the iterator stays valid. Obviously the node gets deleted when the list is destructed...

xtofl
+5  A: 

Iterators to list are invalidated only if the list is destroyed or the "pointed" element is removed from the list.

AProgrammer
+1  A: 

Storing the iterator for the list should be fine. It will not get invalidated unless you remove the same element from the list for which you have stored the iterator. Following quote from SGI site:

Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed

However, note that the previous and next element of the stored iterator may change. But the iterator itself will remain valid.

Naveen
he didn't say anything about modifying the list, so I fail to see how invalidation could be an issue in the first place.
jalf
A: 

Yes. List is the way to go.You can refer my answer to similar question here: What is the lifetime and validity of C++ iterators:

aJ
it'd work with any iterator, not just list. The question says nothing about modifying the list, so lifetime or validity aren't really relevant
jalf
+4  A: 

Yes, it'll work fine.

Since so many other answers go on about this being a special quality of list iterators, I have to point out that it'd work with any iterators, including vector ones. The fact that vector iterators get invalidated if the vector is modified is hardly relevant to a question of whether it is legal to store iterators in another container -- it is. Of course the iterator can get invalidated if you do anything that invalidates it, but that has nothing to do with whether or not the iterator is stored in a stack (or any other data structure).

jalf
+1  A: 

This might be offtopic, but just a hint...

Be aware, that your function(s)/data structure would probably be thread unsafe for read operations. There is a kind of basic thread safety where read operations do not require synchronization. If you are going to store the sate how much the caller read from your structure it will make the whole concept thread unsafe and a bit unnatural to use. Because nobody assumes a read to be state-full operation.

If two threads are going to call it they will either need to synchronize the calls or your data structure might end-up in a race condition. The problem in such a design is that both threads must have access to a common synchronization variable.

I would suggest making two overloaded functions. Both are stateless, but one of them should accept a hint iterator, where to start next read/search/retrieval etc. This is e.g. how Allocator in STL is implemented. You can pass to allocator a hint pointer (default 0) so that it quicker finds a new memory chunk.

Regards,
Ovanes

ovanes
Thanks for the hint, ovanes. But the problem would not occur in my case because state for each thread is stored in a separate place. Only one thread would read from the containers at a time. I'm not sure I understand the overloaded functions way completely, I'll have to read about Allocators, but thanks for the suggestion also. It sounds interesting
Sahasranaman MS