44

I have already the list pointer of CDrawObject*

std::list<CDrawObject*> elements; 

How I can move some element to the end of list. I see STL Algorithms Reference but i don't find this operations. How i can do it?

3
  • 9
    Not 100% pertinent with your question, but are you sure that a linked list of pointers is a sensible data structure choice? There are only a few cases in which I'd consider it the best option... Commented Feb 6, 2011 at 8:49
  • 1
    It is when what he is doing is moving an item from the middle of the list to the end. list is the only collection in which doing this is constant time. Commented Feb 6, 2011 at 17:55
  • 1
    @CashCow: That time, though constant, might still be longer than it takes to std::memmove() the content of a std::vector of containers, especially when aspects like locality of data (CPU cache) is taken into account. Commented Oct 22, 2013 at 7:28

3 Answers 3

84

Use the list method splice()

void list::splice ( iterator position, list<T,Allocator>& x, iterator i );

Move iterator i from list x into current list at position "position"

Thus to move it to the end put

x.splice( x.end(), x, iter ); 

(they can both be the same list or different lists as long as the list from which the item is moved has the same type, both T and Allocator)

Sign up to request clarification or add additional context in comments.

6 Comments

In your example, what if iter is already pointing to the last element—is it necessary to special-case that?
It should not be necessary to test for it, and the library function should still work. Whether it would be as optimal is not certain as the C++ spec only says what the outcome of a function must be and not whether it must be done in the most optimal way.
WARNING: there is a danger in using splice with list. It can invalidate all iterators even when splicing to itself... This is somewhat unexpected from a list data type where one of the advantages to using list is that its most iterators remain valid when things are added removed. But this is not the case with splice so if you are counting on this behavior you might want to use this answer instead: stackoverflow.com/a/4912419/3768831
@RickWildes can you give an example or reference for this statement?
@RickWildes your warning is incorrect. en.cppreference.com/w/cpp/container/list/splice : No iterators or references become invalidated, the iterators to moved elements remain valid
|
3

A std::list is a doubly-linked list, which means you do not have random access to element n. You have to can remove the element, and then use push_back.

5 Comments

No you don't have to do it that way and the poster was too quick to accept the answer.
I didn't mean "have to" in the sense of "that's the only way", but anyway, @G-71 feel free to un-accept my answer if another answer is better.
+1 totally acceptible for a container of pointers. If copying a T is more costly, though, splicing should be preferred.
It'll be problematic if the list contains custom objects. In that case remove destructs the object, and it could be non-trivial to re-construct a new one.
The random access ability has nothing to do with the ability of moving an item from one (already known) position (you already have iterator for) to another.
-3

Remove it then append it to your list.

4 Comments

This isn't as efficient as the chosen answer.
using splice also does not invalidate iterators while this does
@Sopel you might want to check this out: stackoverflow.com/q/143156/3768831 splice does indeed invalidate iterators. Even more so then this does.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.