Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does std::move() invalidate iterators? [duplicate]

Consider the following program:

struct list_wrapper
{
    std::vector<int>    m_list;
};

int main()
{
    std::vector<int> myList { 1, 1, 2, 3, 5 };

    const std::vector<int>::iterator iter = myList.begin();

    list_wrapper wrappedList;
    wrappedList.m_list = std::move(myList);

    // Can I still dereference iter?

    return 0;
}

After the call to std::move(myList), does iter now point to a valid item inside wrappedList.m_list, or do move constructors/assignments invalidate all iterators?

like image 608
Karl Nicoll Avatar asked Dec 29 '16 17:12

Karl Nicoll


People also ask

Does std :: move invalidate iterators?

For reference, std::vector::swap does not invalidate iterators.

What does std :: move () do?

std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

What invalidates an iterator?

Iterator Invalidation in C++ When the container to which an Iterator points changes shape internally, i.e. when elements are moved from one position to another, and the initial iterator still points to the old invalid location, then it is called Iterator invalidation. One should be careful while using iterators in C++.

How do you avoid iterator invalidation in C++?

To avoid invalidation of references to elements you can use a std::deque if you do not insert or erase in the middle. To avoid invalidation of iterators you can use a std::list.

What does the move iterator do in STL?

The move iterator wraps another iterator, and returns an r-value reference of what the wrapped iterator returns when it is dereferenced. When dereferenced (with * or ->), STL containers (like vectors) iterators return a reference to the element they point to.

What is the use of move iterator in C++?

The purpose of the move iterator is to allow the STL to move the objects it manipulates, instead of copying them. Indeed, the STL makes copies by default. In the following example: std::vector<std::string> source = { "Move", "iterators", "in", "C++" }; std::vector<std::string> destination (begin (source), end (source));

How to lose data when using move iterators in Python?

There is a way to lose your data when using move iterators. The idea is that if the elements in source are moved to some other place than destination, then in the end they are neither in source nor in destination so they are effectively lost.

What does it mean to dereference an iterator?

When dereferenced (with * or -> ), STL containers (like vectors) iterators return a reference to the element they point to. Dereferencing a move iterator has the equivalent effect of calling std::move on the reference returned by the wrapped iterator, to convert it into an r-value reference.


1 Answers

After http://en.cppreference.com notes (emphasis mine):

After container move assignment (overload (2)), unless elementwise move assignment is forced by incompatible allocators, references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in *this. The current standard makes this guarantee via the blanket statement in §23.2.1[container.requirements.general]/12, and a more direct guarantee is under consideration via LWG 2321

Notes

As hvd have rightly pointed out there is at least once case where the move assignent is forced to invalidate iterators - when the new container has incompatible allocator.

As Ben Voigt noted there is a broader discussion in this topic over here and it actually already covers the c++11 aspects of the question...

like image 89
W.F. Avatar answered Oct 28 '22 20:10

W.F.