4

I'm reading how "list::splice" works and I don't understand something:

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)

  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  it = mylist1.begin();
  std::advance(it,3);           // "it" points now to 30

  mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                                // mylist1: 30 3 4 1 10 20

in the first and third splice the it iterator is still valid, but why isn't it in the second splice?

According to the documentation:

Iterator validity

No changes on the iterators, pointers and references related to the container before the call. The iterators, pointers and references that referred to transferred elements keep referring to those same elements, but iterators now iterate into the container the elements have been transferred to.

thus it should still be valid

Johnny Pauling
  • 12,701
  • 18
  • 65
  • 108

2 Answers2

4

It's only a guess, but they might have written that to imply that it is now "invalid" in the sense that it is no longer a valid iterator of mylist1, but instead becomes a valid iterator of mylist2.

But still, and I guess you already knew that, it is a valid iterator, so the wording is misleading. You need to be careful, though, as it means that after the second splice-operation, for example, you can no longer do:

std::distance( mylist1.begin(), it );

but need to use

std::distance( mylist2.begin(), it );

as the first would be illegal.

The standard clearly defines it that way in:

23.3.5.5 list operations [list.ops]

void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);

7 Effects: Inserts an element pointed to by i from list x before position and removes the element from x. The result is unchanged if position == i or position == ++i. Pointers and references to *i continue to refer to this same element but as a member of *this. Iterators to *i (including i itself) continue to refer to the same element, but now behave as iterators into *this, not into x.

So, if your compiler/STL invalidates the iterator, this is clearly a bug.

Community
  • 1
  • 1
Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
1

Apparently (since I'm using MSVC2012) the behavior is different:

http://msdn.microsoft.com/en-us/library/72fb8wzd.aspx

In all cases, only iterators or references that point at spliced elements become invalid.

Thus when I have iterators to elements that get moved from one container to another, these iterators become invalid.

I'd be interested in knowing if this behavior is the standard one, though.

Johnny Pauling
  • 12,701
  • 18
  • 65
  • 108
  • why is the microsoft library implemented in a different way ? any sane reason ? – sumanth232 Oct 30 '15 at 14:37
  • There's a defect in the Standard, and MSVC2012 apparently follows it to the letter: https://stackoverflow.com/a/143165/4130137 – Anton Sep 04 '19 at 09:14