std::forward_list swap() implementation in C++11 - c++

My assumption is that in a std::list<> the swap function for the list itself is done by swapping the anchor node. The node can access the previous node and update the previous node's next pointer easily to point to the anchor of the other list; but this cannot be done in std::forward_list (well, it can be, it is just very costly).
If my assumption is correct, how is swap() implemented in std::forward_list in an efficient manner? And while we are at it, how is swap() implemented for the iterators of std::forward_list?

A std::forward_list is simply a singly-linked rather than doubly-linked list like std::list, therefore you can simply swap the head and tail pointers of the list to accomplish a swap() operation.

This is completely implementation-specific, but if the forward lists are implemented by having the class just store a pointer to the first and last linked list cells, then swap could just swap those two pointers. Since forward-linked lists don't have any back pointers, there aren't any more updates to be made and the whole operation can be done in O(1).
As for swap with iterators, this doesn't actually exchange the linked list cells between the two lists; it just has the first iterator point to the cell referenced by the second iterator and vice-versa. If you want to swap the values being pointed at, then this can be done by just modifying the objects in the linked list cells so that they change values. You don't need to rewire the lists in any way.
Hope the helps!

I think you're confused (or I am confused as to what you're asking). std::forward_list::swap(std::forward_list& other) is trivial, with each list object exchanging pointers to the head of their list (and any other member variables) - just like std::list.
The iterator object doesn't have a swap method. The contained object might, or may use the global swap method - but that operates on the objects, and doesn't mutate the list itself or its nodes.

Related

how elements are stored in list of STL in C++

I was reading about lists in Standard Template library in C++. I read elements can not be accessed using index. Can any one please let me know how the lists are stored in memory? Is it sequential? I know how linked lists are implemented. Are the lists in STL are also implemented in same fashion? i.e. a pointer will be having address of next element?
If that is the case, how increment of iterator is able to point to the next element in the list? Is the increment operator on iterator is overloaded?
std::list<> is a sequence container, as are std::vector<>, std::deque. How they are implemented is implementation-dependent. But their behavior and required characteristics are defined by the standard.
Lists, for example, must have constant-time insertion. A vector does not require constant time insertion but does have other requirements (such as const-time random-access). Such requirements gravitate implementations to common algorithms (std::list is commonly a double-linked-list in the traditional-sense, for example).
Iterators "work" on containers such as std::list<> by attaching container-state to the iterator. A list iterator, for example, could know its iterating container and its "place" in the sequence enumeration via a pointer to the current node in the underlying implementation. Advancing the iterator simply means having it move through the internal node pointer to that pointer's "next".
Don't try to attach too much meaning to the implementation underneath the mandated behavior. So long as the behavioral requirements are met, the underlying implementation could quite-literally be anything.
std::list is usually implemented as a linked list, each node storing a list element and pointers to previous and next nodes. It is common to implement linked lists with bounding fake nodes in the very beginning of the list and at the end of it (it makes the implementation a bit simpler and more beautiful). In gcc implementation they use only one node both for the starting and ending fake nodes, so the list is actually cyclic. This fake node does not contain any list element (if it contained, it would be a problem by many reasons). This node has a non-template type (lets say basic_node) which looks like this:
struct basic_node
{
basic_node * prev, * next;
};
Other, value-containing, nodes are templated:
template <typename T>
struct node : basic_node
{
T value;
};
std::list::iterator stores a pointer to basic_node. This gives the following advantage: most of the iterator's code is independent of the template parameter. For example, to increment the iterator, we can just do something like node_ptr = node_ptr->next;, where node_ptr has type basic_node.
When dereferencing, std::list<T>::iterator can cast the pointer to node to appropriate templated node: return static_cast<node<T> *>(node_ptr)->value;.
List is not stored sequentially. You're looking for std::vector if that's what you want.
From documentation, "Lists are sequence containers that allow constant time insert and erase operations anywhere within the sequence, and iteration in both directions. List containers are implemented as doubly-linked lists"

Get pointer to node in std::list or std::forward_list

I am planning to use std::list in my code, I decided not to use std::forward_list, because for deletions (I figured) the whole list will have to traversed, O(N) complexity for std::forward_list (being a single link list). However, when I looked into the documentation I noticed both the stl containers have O(N) complexity to remove an item.
http://www.cplusplus.com/reference/forward_list/forward_list/remove/
http://www.cplusplus.com/reference/list/list/remove/
After some thinking I figured out why (I think). It's because in both cases, the whole list has to be scanned to find the node first, and then delete it. Is this right?
I then looked into the "erase" and "erase_after" methods, and their complexity is "Linear in the number of elements erased (destructions).". It's because, I am passing an iterator to the node (which is kind of like a "pointer"). However, I cannot (or prefer not to) pass this iterator around in my code to access the data in the node. I am not sure if this iterator will be valid if the list is modified? Thoughts?
My question is, is there a way I can get a pointer to the node in the list. That way, I know it will be valid throughout the lifetime of my program, pass it around. And I can just look into it to get access to my data.
However, I cannot (or prefer not to) pass this iterator around in my code to access the data in the node.
Why not? Iterators are easy to use and are quite lightweight. A pointer isn't better in any way.
I am not sure if this iterator will be valid if the list is modified?
For list, any iterator will remain valid, even if the list is modified. Except, of course, if you erase the particular element that is the iterator points to. But that's kind of obvious, you can' expect to have an iterator (or pointer) to something that doesn't exist any more.
(vector is more dangerous. One small change to a vector can invalidate all its iterators.)
You can take a pointer to any individual element in the list.
list<int> iterator it = find(l.begin(), l.end(), 7); // get an iterator
int * ptr = &*it; // get a pointer to the same element.
The pointer is similar to the iterator in many respects. But the iterator is a little more powerful. An iterator can be incremented or decremented, to access neighbouring elements in the list. And an iterator can be used to delete an element from the list. A pointer cannot do either of those things.
Both the iterator and pointer remain valid as long as that particular element isn't removed.
I am not sure if this iterator will be valid if the list is modified
Yeah, in the general case, storing iterators is risky unless you keep a close eye on the operations performed on your container.
Problem is, this is just the same for a pointer. In fact, for many containers, iterators are implemented as pointers.
So either store an iterator or a pointer if you like but, either way, keep an eye on the iterator invalidation rules:
Iterator invalidation rules
For lists, an iterator is valid even if other items in the list are erased. It becomes garbage when that item the iterator references in the list is removed.
So, as long as you know the iterator you're passing around isn't being removed by some other piece of code, they're safe to hold onto. This seems fragile though.
Even if there was a construct outside of iterators to reference a node in the list, it would suffer from the same fragility.
However, you can have each node contain an std::shared_ptr to the data it stores instead of the object itself and then pass around std::weak_ptr's to those objects and check for expired before accessing those weak_ptr's.
eg
instead of
std::list<MyClass> foo;
you would have
std::list<std::shared_ptr<MyClass>> foo;
have a look here for info on weak_ptr's
is there a way I can get a pointer to the node in the list
Yes, in your particular implementation.
No, in a standard-compliant way.
If you look at the std::list documentation, there is not a single word about a node. While it is hard to imagine a different way to implement the std::list other than using a doubly linked list, there is nothing that prevents it.
You should almost never come into any contact with undocumented internals of libraries.
Adding, removing and moving the elements within the list or across several lists does not invalidate the iterators or references. An iterator is invalidated only when the corresponding element is deleted.
Source: https://en.cppreference.com/w/cpp/container/list
So a std::list<>::iterator is only invalidated when the corresponding element is deleted. So yes, as long as you make sure that the corresponding element exists (which you will anyway have to do in your scenario of storing/passing around a pointer to anything) you can save and/or pass around the iterator throughout the lifetime of your program.
Now, an iterator is nothing but a pointer in disguise. So, if you prefer to save/pass around the corresponding pointer instead of iterator, you can always first convert the iterator to the pointer as #Aaron McDaid suggested.
int * ptr = &*it; // get a pointer to the same element.

Single linked lists & time complexity

I'm trying to write my own (as close to standard as possible) single linked list implementation. However I am wondering what time complexity people expect of such a list?
Especially for inserting I am wondering how I should implement it. I've read some locations around the internet, where some say inserting is O(1) while others say O(n) - all agree that a double linked list is O(1). However I think O(1) is the case for single linked lists too?
As long as you know the preceding node you just let the preceding node point to the new new, and the new node will point towards where the preceding node did originally point to.
That said it makes me wonder how people expect insert to behave? Normally it inserts elements BEFORE the given iterator. However with a single-linked-list it is hard to do so (one would have to go through O(n) time to get the preceding element & then use above method). Is it common in such lists to make insert place items behind the current iterator? Or -probably better- is there another common function for this?
The complexity of the insertion depends on what you need to do. If you know preceding node (actually, a suitable handle to change the preceding node's "next pointer" is all you need), the complexity is O(1). If you need to find the location where to insert, the complexity is O(n).
With respect to the expectation, I would expect the insert() to behave the same as for doubly linked lists but I also realize that you can't achieve this: You either need to have a different time complexity (to find the predecessor node) or different iterator invalidation semantics (i.e., iterators to other nodes get invalidated). I think the C++ 2011 std::forward_list class template went for a different interface but retaining the guarantees on iterator validity.
To briefly explain why the iterator validity can be effected: An iterator doesn't have to only know about the current node. Instead, it could, for example, point to the predecessor's next pointer. When dereferencing the iterator, it would dereference first its pointer to the next pointer and then this pointer to get hold of the actual node. In return, it is possible to insert in front of the iterator because the iterator knows which next pointer to update. Unfortunately, this means that iterators may get invalidated because the pointer they point to may have changed and they would reference a different node (when erasing nodes, the iterator may have been moved to be entirely invalid although the node referenced is still there).

Accessing the head from anywhere STL list

In order to get the next element in the list one just needs to increase the iterator. However from any element in the list, is there a way to get directly to the head of a list? For example if iterator is pointing to the third element of a list, is there a way to get to the front of the list besides iterating backwards ?
Thanks
No, because std::list is designed to model a doubly-linked list (and is usually implemented as one), and in a doubly linked list, each element only has pointers to the previous and next element in the list.
No, and you cannot even do it just based on having one single iterator: You have no way of knowing whether the iterator is valid, and whether you are allowed to increment or decrement it!
The only way you could do it would be by comparing your iterator (presumed valid) to x.begin() and x.end(), but once you have those, you already have the iterator to the list head and the question becomes moot.
Iterators should always be thought of as coming in pairs [first, last), and containers provide such a pair with their begin()/end() member functions.

Storing iterators inside containers

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.
Iterators to list are invalidated only if the list is destroyed or the "pointed" element is removed from the list.
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).
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.
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
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.
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...